我有一个包含对象数组的对象。
obj = {};
obj.arr = new Array();
obj.arr.push({place:"here",name:"stuff"});
obj.arr.push({place:"there",name:"morestuff"});
obj.arr.push({place:"there",name:"morestuff"});
我想知道从数组中删除重复对象的最佳方法是什么。例如,obj.arr将变成。。。
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
在一行中使用ES6+,您可以按键获得唯一的对象列表:
const key = 'place';
const unique = [...new Map(arr.map(item => [item[key], item])).values()]
可以将其放入函数中:
function getUniqueListBy(arr, key) {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
下面是一个工作示例:
常量arr=[{地点:“这里”,名称:“x”,其他:“其他stuff1”},{地点:“那里”,名称:“x”,其他:“其他stuff2”},{地点:“这里”,名称:“y”,其他:“其他stuff4”},{地点:“这里”,名称:“z”,其他:“其他stuff5”}]函数getUniqueListBy(arr,key){return[…new Map(arr.Map(item=>[item[key],item])).values()]}const arr1=getUniqueListBy(arr,'place')console.log(“按位置唯一”)console.log(JSON.stringify(arr1))console.log(“\n名称唯一”)const arr2=getUniqueListBy(arr,'name')console.log(JSON.stringify(arr2))
它是如何工作的
首先,以可以用作Map输入的方式重新映射数组。
arr.map(项=>[项[键],项]);
这意味着阵列的每个项目将被转换为具有2个元素的另一个阵列;选定的键作为第一个元素,整个初始项作为第二个元素,这称为条目(例如数组条目、映射条目)。这是一个官方文档,其中有一个示例显示了如何在Map构造函数中添加数组项。
放置钥匙时的示例:
[["here", {place: "here", name: "x", other: "other stuff1" }], ...]
其次,我们将这个修改后的数组传递给Map构造函数,这就是神奇的发生。映射将消除重复的关键字值,只保留同一关键字的最后插入值。注意:贴图保持插入顺序。(检查贴图和对象之间的差异)
新映射(上面刚刚映射的条目数组)
第三,我们使用map值来检索原始项,但这次没有重复项。
新映射(mappedArr).values()
最后一个是将这些值添加到一个新的数组中,这样它可以看起来像初始结构,并返回:
return[…new Map(mappedArr).values()]
我认为,将reduce与JSON.stringify结合起来以完美地比较对象,并选择性地添加那些尚未在累加器中的对象是一种优雅的方式。
请记住,在极端情况下,JSON.stringify可能会成为一个性能问题,因为阵列有许多对象,而且它们很复杂,但在大多数情况下,这是IMHO的最短路径。
var集合=〔{a:1},{a:2},{a:1},{a:3}〕var filtered=collection.reduce((已过滤,项)=>{if(!filtered.some(filteredItem=>JSON.stringify(filtered item)==JSON.sstringify(item)))已过滤推送(项)返回已过滤}, [])console.log(已过滤)
另一种写法相同(但效率较低):
collection.reduce((filtered, item) =>
filtered.some(filteredItem =>
JSON.stringify(filteredItem ) == JSON.stringify(item))
? filtered
: [...filtered, item]
, [])
带有Map的一行程序(高性能,不保留顺序)
在数组arr中查找唯一id。
const arrUniq = [...new Map(arr.map(v => [v.id, v])).values()]
如果订单很重要,请检查带过滤器的解决方案:带过滤器的方案
由数组arr中的多个财产(位置和名称)唯一
const arrUniq = [...new Map(arr.map(v => [JSON.stringify([v.place,v.name]), v])).values()]
由数组arr中的所有财产唯一
const arrUniq = [...new Map(arr.map(v => [JSON.stringify(v), v])).values()]
保留数组arr中的第一次出现
const arrUniq = [...new Map(arr.slice().reverse().map(v => [v.id, v])).values()].reverse()