Как фильтровать массив, когда значение ключа объекта находится в массиве

У меня есть модель массива, как показано ниже:

records:[{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":2,
    "fname": "A",
    "lname": "Y"
},
{
    "empid":3,
    "fname": "B",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

Теперь у меня есть массив empid [1,4,5].

Итак, теперь мне нужно отфильтровать первый массив, который содержит все ключи во втором.

Вывод:

records:[{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

Я могу сделать это, используя цикл forEach в angular, но поскольку у меня более 100 записей в объекте моей модели. Мне нужно предложение о том, как справиться с этим гораздо лучше.

Я думаю о создании собственного фильтра, но что вы думаете об этом (если да, предоставьте пример кода для этого).


person krsnaadi    schedule 05.03.2016    source источник
comment
данные и идентификаторы отсортированы?   -  person Nina Scholz    schedule 05.03.2016
comment
Нет, данные не сортируются. Решение Aravindsamy выглядит хорошо. Спасибо, ребята, за быстрый ответ.   -  person krsnaadi    schedule 05.03.2016
comment
Почти дубликат javascript. Как фильтровать массив объектов на основе атрибутов? - Переполнение стека -- хотя в этом случае условие немного сложнее (с includes)   -  person user202729    schedule 16.02.2021


Ответы (7)


Вы можете сделать это с помощью Array.prototype.filter(),

var data = { records : [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }] }
var empIds = [1,4,5]
var filteredArray = data.records.filter(function(itm){
  return empIds.indexOf(itm.empid) > -1;
});

filteredArray = { records : filteredArray };

Если​ ​callBack​ возвращает значение ​true​, то ​itm​, переданное этому конкретному callBack, будет отфильтровано. Подробнее об этом можно прочитать здесь .​​​​​

person Rajaprabhu Aravindasamy    schedule 05.03.2016
comment
Это действительно просто и легко @Rajaprabhu, но любая информация, связанная с производительностью при выполнении этого на массиве больших данных (около 500-1000), - person krsnaadi; 05.03.2016
comment
@KrishnaAditya Это очень похоже на цикл for, внутренне данные будут повторяться с использованием циклов for, но эффективным способом. Это делает код более читабельным и удобным для сопровождения. - person Rajaprabhu Aravindasamy; 05.03.2016

В 2019 году с использованием ES6:

const ids = [1, 4, 5],
  data = {
    records: [{
      "empid": 1,
      "fname": "X",
      "lname": "Y"
    }, {
      "empid": 2,
      "fname": "A",
      "lname": "Y"
    }, {
      "empid": 3,
      "fname": "B",
      "lname": "Y"
    }, {
      "empid": 4,
      "fname": "C",
      "lname": "Y"
    }, {
      "empid": 5,
      "fname": "C",
      "lname": "Y"
    }]
  };


data.records = data.records.filter( i => ids.includes( i.empid ) );

console.info( data );

person Tim Elsass    schedule 17.05.2019
comment
Это лучший ответ. - person Bill Zelenko; 06.08.2019
comment
Некоторые слова объяснения значительно увеличат ценность вашего ответа для новичков в JavaScript. ;) - person Andreas; 10.08.2020

Это быстрое решение с временным объектом.

var records = [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }],
    empid = [1, 4, 5],
    object = {},
    result;

records.forEach(function (a) {
    object[a.empid] = a;
});

result = empid.map(function (a) {
    return object[a];
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

person Nina Scholz    schedule 05.03.2016
comment
Да, это даже выглядит хорошо. Скорее всего, по мере поиска хеш-ключа я проверю и этот. Спасибо @Нина - person krsnaadi; 05.03.2016

Вы можете использовать функцию Array#filter и дополнительный массив для хранения отсортированных значений;

var recordsSorted = []

ids.forEach(function(e) {
    recordsSorted.push(records.filter(function(o) {
        return o.empid === e;
    }));
});

console.log(recordsSorted);

Результат:

[ [ { empid: 1, fname: 'X', lname: 'Y' } ],
  [ { empid: 4, fname: 'C', lname: 'Y' } ],
  [ { empid: 5, fname: 'C', lname: 'Y' } ] ]
person isvforall    schedule 05.03.2016

Самый быстрый способ (потребуется дополнительная память):

var empid=[1,4,5]
var records = [{ "empid": 1, "fname": "X", "lname": "Y" }, { "empid": 2, "fname": "A", "lname": "Y" }, { "empid": 3, "fname": "B", "lname": "Y" }, { "empid": 4, "fname": "C", "lname": "Y" }, { "empid": 5, "fname": "C", "lname": "Y" }] ;

var empIdObj={};

empid.forEach(function(element) {
empIdObj[element]=true;
});

var filteredArray=[];

records.forEach(function(element) {
if(empIdObj[element.empid])
    filteredArray.push(element)
});
person me_astr    schedule 05.03.2016

Если у вас есть пары ключ-значение во входном массиве, я использовал:

.filter(
          this.multi_items[0] != null && store.state.isSearchBox === false
            ? item =>
                _.map(this.multi_items, "value").includes(item["wijknaam"])
            : item => item["wijknaam"].includes("")
        );

где входной массив представляет собой multi_items как: [{"text": "bla1", "value": "green"}, {"text": и т. д. и т. д.}]

_.map — это функция lodash.

person Peter van der Lely    schedule 01.11.2019

Старый способ сделать это. Многие могут ненавидеть этот способ, но я все еще много раз нахожу, что это все же лучше, с моей точки зрения.

Ввод:

var records = [{
    "empid":1,
    "fname": "X",
    "lname": "Y"
},
{
    "empid":2,
    "fname": "A",
    "lname": "Y"
},
{
    "empid":3,
    "fname": "B",
    "lname": "Y"
},
{
    "empid":4,
    "fname": "C",
    "lname": "Y"
},
{
    "empid":5,
    "fname": "C",
    "lname": "Y"
}
]

var newArr = [1,4,5];

Код:

var newObj = [];
for(var a = 0 ; a < records.length ; a++){
 if(newArr.indexOf(records[a].empid) > -1){
  newObj.push(records[a]);
 }
}

Метод indexOf() возвращает первый индекс, по которому данный элемент может быть найден в массиве, или -1, если он отсутствует.

Ссылка — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

Вывод:

[{
    "empid": 1,
    "fname": "X",
    "lname": "Y"
}, {
    "empid": 4,
    "fname": "C",
    "lname": "Y"
}, {
    "empid": 5,
    "fname": "C",
    "lname": "Y"
}]
person aditya    schedule 16.02.2021