У меня есть 2 массива в моем приложении Ember, один массив содержит строку идентификаторов, а другой содержит объекты Ember.

Я хочу отправить объекты Ember в функцию, получить массив идентификаторов из файла cookie, хранящегося в браузере, а затем отфильтровать объекты Ember, если свойство ID соответствует строке в моем массиве IDS.

Я пытаюсь использовать фильтр для этого, но каждый раз он просто возвращает полный список объектов Ember, даже если в массиве строк идентификаторов содержится идентификатор. Вот мой код из моего компонента Ember ..

init () {
        this._super(...arguments);

this.get('userNotificationServices').fetchActiveUserNotifications().then(result => {
            this.updatedArray = this.filterArray(result);
            this.set('activeNotifications', result);
        });

    },

filterArray(currentActiveNotifications) {
    var ids;
    var currentNonDimissedNotifications;
    if (this.getCookie("dismissed-notifications")) {
        ids = this.getCookie("dismissed-notifications").split(',');
        currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
            for (var id in ids) {
                return obj.id !== id;
            }
        });
    }
    return currentNonDimissedNotifications;
}
0
Nick Pocock 21 Мар 2017 в 12:54

2 ответа

Лучший ответ

Есть две проблемы с вашим filter:

currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    for (var id in ids) {
        return obj.id !== id;
    }
});
  1. Он всегда возвращает результат проверки first ; он никогда не делает последующих проверок, потому что вы используете return безоговорочно.

  2. Вы использовали for-in, что означает, что id будет индексом каждой записи, а не ее значением. Подробнее о зацикливании массивов и о том, почему for-in не подходит в большинстве случаев, в моем ответе здесь .

Мы хотим вернуться только тогда, когда мы либо нашли совпадение (мы можем сразу же остановиться), либо прошли через весь массив идентификаторов, и мы хотим выполнить цикл правильно.

Так может быть:

currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    for (var i = 0; i < ids.length; ++i) { // Note loop
        if (obj.id === ids[i]) {
            // Found it, so we want to filter it out
            return false;
        }
    }
    // Didn't find it, so keep it
    return true;
});

Живой пример:

var currentActiveNotifications = [
  {id: 1},
  {id: 2},
  {id: 3}
];
var ids = [2, 3];
var currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    for (var i = 0; i < ids.length; ++i) { // Note loop
        if (obj.id === ids[i]) {
            // Found it, so we want to filter it out
            return false;
        }
    }
    // Didn't find it, so keep it
    return true;
});
console.log(currentNonDimissedNotifications);

... но массивы имеют удобную функцию indexOf, которая позволяет нам проверять, есть ли значение в массиве (более новые версии JavaScript также имеют includes). Таким образом, мы можем использовать это:

currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    return ids.indexOf(obj.id) === -1;
});

Живой пример:

var currentActiveNotifications = [
  {id: 1},
  {id: 2},
  {id: 3}
];
var ids = [2, 3];
var currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    return ids.indexOf(obj.id) === -1;
});
console.log(currentNonDimissedNotifications);

Или с более новым includes:

currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    return !ids.includes(obj.id);
});

Живой пример:

var currentActiveNotifications = [
  {id: 1},
  {id: 2},
  {id: 3}
];
var ids = [2, 3];
var currentNonDimissedNotifications = currentActiveNotifications.filter(function (obj) {
    return !ids.includes(obj.id);
});
console.log(currentNonDimissedNotifications);
1
Community 23 Май 2017 в 12:10

Вы не должны использовать цикл for для фильтрации объектов, потому что return obj.id !== id; всегда будет возвращать true и также проверяет только первый идентификатор.

Попробуйте использовать indexOf:

currentNonDimissedNotifications = currentActiveNotifications.filter(function(obj) {
  return ids.indexOf(obj.id) === -1
});
0
dfsq 21 Мар 2017 в 10:06