Неожиданный результат при фильтрации одного массива объектов по двум другим массивам объектов - PullRequest
1 голос
/ 08 июля 2019

Я пытаюсь отфильтровать объекты из массива "a", которые соответствуют объектам в массиве "b" и "c". вот ссылка на jsfiddle для проверки кода.

Вот что у меня сейчас есть:

const a = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "sofie",
  "uq_id": "abc2"
}, {
  "name": "casper",
  "uq_id": "abc3"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const b = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const c = [{
  "name": "casper",
  "uq_id": "abc3"
}];

function sort(a, b, c) {
  result = [];
  console.log(result);
  if (b !== null) {
    result = a.filter(function(item) {
      return !b.includes(item.uq_id);
    })
  }
  if (c !== null) {
    result = result.filter(function(item) {
      return !c.includes(item.uq_id);
    })
  }
  console.log(result);
}

sort(a, b, c);

Я ожидаю следующий вывод:

[{name="sofie", uq_id="abc2"}]

Но по какой-то причине он выдает:

[{name="sondre", uq_id="abc1"},
{name="sofie", uq_id="abc2"},
{name="casper", uq_id="abc3"},
{name="odin", uq_id="abc4"}]

Кто-нибудь знает, как я могу заставить это работать так, как я задумал?

Ответы [ 3 ]

2 голосов
/ 08 июля 2019

Если цель состоит в том, чтобы отфильтровать записи из a, для которых name соответствует записи в b или c, вы не можете использовать includes, если только записи в a, b и c относятся к одинаковым объектам (не только эквивалентным).

Предполагая, что это не так, вы можете использовать some, чтобы узнать, содержит ли массив совпадение для name. Вы можете использовать &&, чтобы увидеть, что нет совпадений ни в b, ни в c:

const filtered = a.filter(entry => {
    return !b.some(({name}) => entry.name === name) &&
           !c.some(({name}) => entry.name === name);
});

Live Copy:

const a = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "sofie",
  "uq_id": "abc2"
}, {
  "name": "casper",
  "uq_id": "abc3"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const b = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const c = [{
  "name": "casper",
  "uq_id": "abc3"
}];

function filter(a, b, c) {
    const filtered = a.filter(entry => {
        return !b.some(({name}) => entry.name === name) &&
               !c.some(({name}) => entry.name === name);
    });
    return filtered;
}

console.log(filter(a, b, c));

Это также можно выразить с помощью every, в зависимости от того, что вы предпочитаете:

const filtered = a.filter(entry => {
    return b.every(({name}) => entry.name !== name) &&
           c.every(({name}) => entry.name !== name);
});

Если b и c действительно больших (сотни тысяч записей, возможно, миллионов), которые могут быть недостаточно эффективными, чтобы оправдать сначала создание Set имен:

const names = new Set([
  ...b.map(({name}) => name),
  ...c.map(({name}) => name)
]);
const filtered = a.filter(entry => {
    return !names.has(entry.name);
});

Или вы можете просто сделать это для предпочтения или ясности.

Live Copy:

const a = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "sofie",
  "uq_id": "abc2"
}, {
  "name": "casper",
  "uq_id": "abc3"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const b = [{
  "name": "sondre",
  "uq_id": "abc1"
}, {
  "name": "odin",
  "uq_id": "abc4"
}];

const c = [{
  "name": "casper",
  "uq_id": "abc3"
}];

function filter(a, b, c) {
    const names = new Set([
      ...b.map(({name}) => name),
      ...c.map(({name}) => name)
    ]);
    const filtered = a.filter(entry => {
        return !names.has(entry.name);
    });
    return filtered;
}

console.log(filter(a, b, c));
1 голос
/ 08 июля 2019

b и c - массивы объектов, в которые входят только объекты.Вам нужно использовать some(), чтобы сравнить uq_id

const a = [{
    "name": "sondre",
    "uq_id": "abc1"
}, {
    "name": "sofie",
    "uq_id": "abc2"
}, {
    "name": "casper",
    "uq_id": "abc3"
}, {
    "name": "odin",
    "uq_id": "abc4"
}];

const b = [{
    "name": "sondre",
    "uq_id": "abc1"
}, {
    "name": "odin",
    "uq_id": "abc4"
}];

const c = [{
    "name": "casper",
    "uq_id": "abc3"
}];

sort(a, b, c);



function sort(a, b, c) {
    let result = [];
    if (b !== null) {
        result = a.filter(function(item) {
            return !b.some(x => x.uq_id === item.uq_id);
        })
    }
    if (c !== null) {
        result = result.filter(function(item) {
            return !c.some(x => x.uq_id === item.uq_id);
        })
    }
    console.log(result);
}
0 голосов
/ 08 июля 2019

Достаточно одного фильтра:

const a = [ { "name": "sondre", "uq_id": "abc1" }, 
            { "name": "sofie" , "uq_id": "abc2" }, 
            { "name": "casper", "uq_id": "abc3" }, 
            { "name": "odin"  , "uq_id": "abc4" } ];

const b = [ { "name": "sondre", "uq_id": "abc1" }, 
            { "name": "odin"  , "uq_id": "abc4" } ];

const c = [ { "name": "casper", "uq_id": "abc3" } ];


const result = a.filter(x => !b.some(y => x.uq_id === y.uq_id) 
                          && !c.some(y => x.uq_id === y.uq_id));

console.log(result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...