将一个对象数组与其他两个对象数组过滤时出现意外结果

时间:2019-07-08 10:51:32

标签: javascript arrays object

我正在尝试从数组“ 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 个答案:

答案 0 :(得分:2)

如果目标是从anameb上的条目匹配的c中过滤出条目,则不能使用includes除非abc中的条目引用相同对象(而不仅仅是等效对象)。

假设它们不存在,则可以使用some来确定数组是否包含name的匹配项。您需要使用&&来查看bc中都没有匹配项:

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

实时复制:

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);
});

如果bc 真的大(成千上万个条目,也许是数百万个),可能不足以证明创建Set个首先命名:

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

或者您可能只是出于偏好或清晰性而这么做。

实时复制:

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 :(得分:1)

bc是对象数组,仅包含对象。您需要先使用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);
}

答案 2 :(得分:0)

一个过滤器就足够了:

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);