如果我有一个类似的数组:
[
{
id: 1,
title: 'foo'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
},
{
id: 4,
title: 'bantz'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
}
]
我想返回一个包含任何只出现一次的对象的数组。因此,对于此示例,所需的输出将是:
[
{
id: 1,
title: 'foo'
},
{
id: 4,
title: 'bantz'
}
]
我尝试过使用reduce()
和indexOf()
解决此问题的一些不同方法,例如this解决方案,但它们不适用于某些对象原因。
非常感谢任何协助。
答案 0 :(得分:3)
做这样的事情:
const data = [
{
id: 1,
title: 'foo'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
},
{
id: 4,
title: 'bantz'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
}
];
const isEqual = (a, b) => a.id === b.id;
const unique = (arr) => arr.reduce((result, a, index) =>
result.concat(arr.some(b => a !== b && isEqual(a, b)) ? [] : a)
, []);
console.log(unique(data));
在这种情况下,我们将每个元素循环到reduce()
,在添加之前,我们会在添加之前看到数组中是否存在其他版本的元素。我们必须确保没有自己也不平等(否则我们会得到一个空数组)。
isEqual()
是一个单独的功能,可以轻松定制“相等”的含义。
如上所述,data
中的每个元素都是唯一的,它们都是独立的对象。 data[0] === data[4]
为false
,即使它们具有相同的数据。您必须比较内部数据以确定它们是否重复。正如Paulpro之前提到的,{} === {}
也是false
,因为它们是两个不同的对象,即使它们的值相同。
console.log({} === {});
console.log({ a: 1 } === { a: 1 });
在isEqual()
的示例版本中,如果它们具有相同的ID,我认为它们是相同的。
做这样的事情:
const data = [
{
id: 1,
title: 'foo'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
},
{
id: 4,
title: 'bantz'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
}
];
const isEqual = (a, b) => a.id === b.id;
const unique = (arr) => arr.reduce((result, a) =>
result.concat(result.some(b => isEqual(a, b)) ? [] : a)
, []);
console.log(unique(data));
我将isEqual()
拆分为它自己的功能,这样您就可以轻松定义“相等”的含义。有人指出,从技术上讲,即使数据不同,所有这些都是独一无二的。在我的例子中,我将等号id定义为等于。
然后我使用reduce来遍历每个并构建一个对象。在我将它添加到数组之前(通过concat()
),我使用some()
遍历所有这些并继续直到找到一个相等的(我不会包含)或者没有相等的我加了它。
答案 1 :(得分:3)
您可以使用Map
来避免不得不一次又一次地浏览数组,这会导致效率低的 O(n²)时间复杂度。这是 O(n):
function getUniquesOnly(data) {
return Array.from(
data.reduce( (acc, o) => acc.set(o.id, acc.has(o.id) ? 0 : o), new Map),
(([k,v]) => v)
).filter( x => x );
}
var data = [
{
id: 1,
title: 'foo'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
},
{
id: 4,
title: 'bantz'
},
{
id: 2,
title: 'bar'
},
{
id: 3,
title: 'bat'
}
];
console.log(getUniquesOnly(data));
答案 2 :(得分:0)
简单的实现看起来像这样:
这实质上就是你发布的解决方案的工作方式,除了你的数组中的所有值都是 - 在JavaScript的眼中 - 是唯一的。因此,您需要定义自己的比较值的方法。
.reduce方法可以这样使用:
function areEqual(a, b) { /* define how you want the objects compared here */ }
function contains(a, lst) {
return lst.reduce(function (acc, x) {
return acc || areEqual(a, x);
}, false);
}
function getUnique(lst) {
return lst.reduce(function (acc, x) {
if(!contains(x, acc))
{
acc.push(x);
}
return acc;
}, []);
}
您可能希望了解JavaScript对象比较的工作原理。为了深入比较(听起来你想要的),我会看existing answers。