Я использую response-native, где мне нужно отфильтровать объекты из массива объектов на основе id, который предоставляется в другом массиве объектов. у меня есть объект массива как:

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];
var filterResult = objArr.filter((f) => {
                      !this.keys.includes(f)
                   });

Как удалить объекты из массива, где id равен идентификатору пользователя ключей?

1
Shubham Kumar 2 Янв 2018 в 21:18

2 ответа

Лучший ответ

Один из способов сделать это - уменьшить объекты ключей до массива чисел. Идея состоит в том, чтобы сравнить каждый element.id в вашем objArr с идентификаторами в вашем массиве ключей. Это похоже на то, что вы пытаетесь сделать выше.

1) Уменьшить ключи:

var reducedKeys = keys.reduce((total, each) => {
   total.push(each.user_id);
   return total;
}, []);

2) Отфильтровать идентификаторы, не включенные в ключи:

var filterResult = objArr.filter((each) => {
   if (!reducedKeys.includes(each.id)) {
       return each;
   }
});

Если ты:

console.log(filterResult)

Результат:

[ { name: 'abc', id: 3 } ]
0
Kit Masaracchia 2 Янв 2018 в 18:42

Для чистого javascript это работает для вашего случая с фильтром и уменьшением (попробуйте запустить ниже фрагмент кода)

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];

var filtered = objArr.filter( (o) => {
    return keys.reduce( (final, k) => {
        return final && !(k.user_id == o.id);
    }, true);
});

console.log(filtered);

Чтобы не изобретать велосипед заново, предложите использовать для этого существующую библиотеку.

lodash делает именно то, что вам нужно, с differenceWith.

Так становится чисто и нарядно:

const filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);

Попробуйте запустить приведенный ниже фрагмент кода.

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];

const filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);

console.log(filtered);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Используйте lodash для react-native:

npm i lodash

А также

import _ from 'lodash';

Обновление 2:

Если вы пишете код, критичный к производительности, это совсем другая история. вы должны настроить свой код, создав индекс, избегайте всех удобных функций, таких как filter, reduce, вместо этого используйте традиционный цикл for.

Я сделал быстрый, он примерно в 50 раз быстрее, чем lodash (от 300 мс до 6 мс), на 100k объектов с 3k ключами:

var filtered = [];
var indexes = {};
for (var i=0; i<keys.length; ++i) {
    indexes[keys[i].user_id] = true;
}
for (var i=0; i<objArr.length; ++i) {
    !indexes[objArr[i].id] && filtered.push(objArr[i]);
}
/* create objects */
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

function makeRand() {
  return Math.floor(Math.random() * 5000);
}

var objArr = [];
for (var i=0; i<100000; ++i) {
    objArr.push({
        name: guid(),
        id: makeRand()
    });
}

var keys = [];
for (var i=0; i<3000; ++i) {
    keys.push({
        user_id: makeRand()
    });
}

/* execute method 1 */
console.time('measure method 1');
var filtered = objArr.filter( (o) => {
    return keys.reduce( (final, k) => {
        return final && !(k.user_id == o.id);
    }, true);
});
console.timeEnd('measure method 1');
console.log('measure method 1 totally', filtered.length, ' objects');

/* execute method 2 */
console.time('measure method 2');
var filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);
console.timeEnd('measure method 2');
console.log('measure method 2 totally', filtered.length, ' objects');

/* execute method 3 */
console.time('measure method 3');
var filtered = [];
var indexes = {};
for (var i=0; i<keys.length; ++i) {
    indexes[keys[i].user_id] = true;
}
for (var i=0; i<objArr.length; ++i) {
    !indexes[objArr[i].id] && filtered.push(objArr[i]);
}
console.timeEnd('measure method 3');
console.log('measure method 3 totally', filtered.length, ' objects');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
0
Val 3 Янв 2018 в 09:44