我有一个包含对象数组的对象。
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"}
arrayWithNoDuplicates = Array.from(new Set(myArray))
来点 es6
魔法怎么样?
obj.arr = obj.arr.filter((value, index, self) =>
index === self.findIndex((t) => (
t.place === value.place && t.name === value.name
))
)
更通用的解决方案是:
const uniqueArray = obj.arr.filter((value, index) => {
const _value = JSON.stringify(value);
return index === obj.arr.findIndex(obj => {
return JSON.stringify(obj) === _value;
});
});
使用上述属性策略而不是 JSON.stringify
:
const isPropValuesEqual = (subject, target, propNames) =>
propNames.every(propName => subject[propName] === target[propName]);
const getUniqueItemsByProperties = (items, propNames) =>
items.filter((item, index, array) =>
index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNames))
);
如果您希望 propNames
属性是数组或值,则可以添加包装器:
const getUniqueItemsByProperties = (items, propNames) => {
const propNamesArray = Array.from(propNames);
return items.filter((item, index, array) =>
index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNamesArray))
);
};
允许 getUniqueItemsByProperties('a')
和 getUniqueItemsByProperties(['a']);
解释
首先了解使用的两种方法:filter、findIndex
过滤器,查找索引
接下来考虑是什么让你的两个对象相等并记住这一点。
我们可以将某物检测为重复,如果它满足我们刚刚想到的标准,但它的位置不是符合标准的对象的第一个实例。
因此,我们可以使用上述标准来确定某物是否是重复的。
一个带过滤器的衬垫(保留顺序)
在数组中查找唯一的 id
。
arr.filter((v,i,a)=>a.findIndex(v2=>(v2.id===v.id))===i)
如果顺序不重要,地图解决方案会更快:Solution with map
由多个属性(place
和 name
)唯一
arr.filter((v,i,a)=>a.findIndex(v2=>['place','name'].every(k=>v2[k] ===v[k]))===i)
所有属性都是唯一的(这对于大型数组来说会很慢)
arr.filter((v,i,a)=>a.findIndex(v2=>(JSON.stringify(v2) === JSON.stringify(v)))===i)
保留最后一次出现,将 findIndex
替换为 findLastIndex
。
arr.filter((v,i,a)=>a.findLastIndex(v2=>(v2.place === v.place))===i)
findIndex
上的 t
代表什么?
在一行中使用 ES6+,您可以通过键获得唯一的对象列表:
const unique = [...new Map(arr.map((item, key) => [item[key], item])).values()]
它可以放入一个函数中:
function getUniqueListBy(arr, key) {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
这是一个工作示例:
const arr = [ {地点:“这里”,名称:“x”,其他:“其他东西1”},{地点:“那里”,名称:“x”,其他:“其他东西2”},{地点:“这里”,名称:“y”,其他:“其他东西4”},{地点:“这里”,名称:“z”,其他:“其他东西5”}] function getUniqueListBy(arr, key) { return [.. .new Map(arr.map(item => [item[key], item])).values()] } const arr1 = getUniqueListBy(arr, 'place') console.log("Unique by place") 控制台。 log(JSON.stringify(arr1)) console.log("\n按名称唯一") const arr2 = getUniqueListBy(arr, 'name') console.log(JSON.stringify(arr2))
它是如何工作的
首先,数组以一种可以用作 Map. 的输入的方式重新映射
arr.map(item => [item[key], item]);
这意味着数组的每个项目都将转换为另一个具有 2 个元素的数组; 选定的键作为第一个元素,整个初始项作为第二个元素,这称为条目(例如 array entries、map entries)。 here is the official doc 有一个示例,展示了如何在 Map 构造函数中添加数组条目。
放置键时的示例:
[["here", {place: "here", name: "x", other: "other stuff1" }], ...]
其次,我们将这个修改后的数组传递给 Map 构造函数,这就是神奇的事情发生了。 Map 将消除重复的键值,仅保留同一键的最后插入值。 注意:地图保持插入顺序。 (check difference between Map and object)
新映射(上面刚刚映射的条目数组)
第三,我们使用地图值来检索原始项目,但这次没有重复。
新地图(mappedArr).values()
最后一个是将这些值添加到一个新的数组中,以便它看起来像初始结构并返回:
返回 [...new Map(mappedArr).values()]
id
。该问题需要整个对象在所有字段(例如 place
和 name
)中都是唯一的
简单而高效的解决方案,比现有的 70 多个答案具有更好的运行时间:
const ids = array.map(o => o.id)
const filtered = array.filter(({id}, index) => !ids.includes(id, index + 1))
例子:
const arr = [{id: 1, name: 'one'}, {id: 2, name: 'two'}, {id: 1, name: 'one'}] const ids = arr.map(o => o.id) const filters = arr.filter(({id}, index) => !ids.includes(id, index + 1)) console.log(filtered)
这个怎么运作:
Array.filter()
通过检查先前映射的 id 数组是否包含当前 id 来删除所有重复对象({id}
将对象分解为仅其 id)。为了只过滤掉实际的重复项,它使用 Array.includes()
的第二个参数 fromIndex
和 index + 1
,这将忽略当前对象和所有以前的对象。
由于 filter
回调方法的每次迭代都只会搜索从当前索引 + 1 开始的数组,因此这也大大减少了运行时间,因为只有以前未过滤的对象才会被检查。
这显然也适用于不称为 id
的任何其他键、多个甚至所有键。
{id: 1, name: 'one'}
和 {namd: 'one', id: 1}
,它将无法检测到重复项。
{ id }
是 destructuring 对象仅插入其 id
键。为了说明这一点,让我们看一下这两个循环:1. arr.forEach(object => console.log(object.id))
和 2. arr.forEach({id} => console.log(id))
。它们都在做同样的事情:打印 arr
中所有对象的 id
键。但是,一种是使用解构,另一种是通过点符号使用更传统的密钥访问。
const arr = [{id: 1, name: 'one'}, {id: 2, name: 'two'}, {id: 1, name: 'THREE'}]
您不想放弃 id=1 的名称吗?是否可以将其保存在数组中?
一个原始的方法是:
const obj = {};
for (let i = 0, len = things.thing.length; i < len; i++) {
obj[things.thing[i]['place']] = things.thing[i];
}
things.thing = new Array();
for (const key in obj) {
things.thing.push(obj[key]);
}
如果您可以使用 underscore 或 lodash 等 Javascript 库,我建议您查看其库中的 _.uniq
函数。从 lodash
:
_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
基本上,您传入数组,这里是一个对象文字,并传入要在原始数据数组中删除重复项的属性,如下所示:
var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name');
更新:Lodash 现在也引入了 .uniqBy
。
let data = [{'v': {'t':1, 'name':"foo"}}, {'v': {'t':1, 'name':"bar"}}];
执行:let uniq = _.uniqBy(data, 'v.t');
我有这个完全相同的要求,即根据单个字段上的重复项删除数组中的重复对象。我在这里找到了代码:Javascript: Remove Duplicates from Array of Objects
因此,在我的示例中,我从数组中删除了具有重复 licenseNum 字符串值的任何对象。
var arrayWithDuplicates = [
{"type":"LICENSE", "licenseNum": "12345", state:"NV"},
{"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
{"type":"LICENSE", "licenseNum": "12345", state:"OR"},
{"type":"LICENSE", "licenseNum": "10849", state:"CA"},
{"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
{"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];
function removeDuplicates(originalArray, prop) {
var newArray = [];
var lookupObject = {};
for(var i in originalArray) {
lookupObject[originalArray[i][prop]] = originalArray[i];
}
for(i in lookupObject) {
newArray.push(lookupObject[i]);
}
return newArray;
}
var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));
结果:
唯一数组是:
[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]
for(var i in array) { if(array[i][prop]){ //valid lookupObject[array[i][prop]] = array[i]; } else { console.log('falsy object'); } }
for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
使用 Set 的一个班轮
var things = new Object(); things.thing = new Array(); things.thing.push({place:"here",name:"stuff"}); things.thing.push({place:"there",name:"morestuff"}); things.thing.push({place:"there",name:"morestuff"}); // 为简洁起见,将 things.thing 分配给 myData var myData = things.thing; things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);控制台.log(things.thing)
解释:
new Set(myData.map(JSON.stringify)) 使用字符串化的 myData 元素创建一个 Set 对象。设置对象将确保每个元素都是唯一的。然后我使用 Array.from 根据创建的集合的元素创建一个数组。最后,我使用 JSON.parse 将字符串化元素转换回对象。
const distinct = (data, elements = []) => [...new Set(data.map(o => JSON.stringify(o, elements)))].map(o => JSON.parse(o));
然后在调用 distinct
时,只需传入元素数组的属性名称。对于将是 ['place', 'name']
的原始帖子。对于@PirateApp 的示例,['a', 'b']
。
ES6 一班轮就在这里
让 arr = [ {id:1,name:"sravan ganji"}, {id:2,name:"pinky"}, {id:4,name:"mammu"}, {id:3,name:"avy "}, {id:3,name:"rashni"}, ]; console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))
cur.id]:cur
中的 :cur
的功能是什么?我不明白这段代码。
_.uniqBy(arr,'id')
做同样的事情
要从对象数组中删除所有重复项,最简单的方法是使用 filter
:
var uniq = {}; var arr = [{"id":"1"},{"id":"1"},{"id":"2"}]; var arrFiltered = arr.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true)); console.log('arrFiltered', arrFiltered);
id
。该问题需要整个对象在所有字段(例如 place
和 name
)中都是唯一的
如果您只需要通过对象的一个字段进行比较,这是使用 Array 迭代方法的另一种选择:
function uniq(a, param){
return a.filter(function(item, pos, array){
return array.map(function(mapItem){ return mapItem[param]; }).indexOf(item[param]) === pos;
})
}
uniq(things.thing, 'place');
这是执行此操作的通用方法:传入一个函数来测试数组的两个元素是否相等。在这种情况下,它比较被比较的两个对象的 name
和 place
属性的值。
ES5 答案
函数 removeDuplicates(arr, equals) { var originalArr = arr.slice(0);变量 i,len,val; arr.length = 0; for (i = 0, len = originalArr.length; i < len; ++i) { val = originalArr[i]; if (!arr.some(function(item) { return equals(item, val); })) { arr.push(val); } } } 函数 thingsEqual(thing1, thing2) { return thing1.place === thing2.place && thing1.name === thing2.name; } var things = [ {place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"} ];删除重复项(事物,事物平等);控制台.log(东西);
原始 ES3 答案
function arrayContains(arr, val, equals) {
var i = arr.length;
while (i--) {
if ( equals(arr[i], val) ) {
return true;
}
}
return false;
}
function removeDuplicates(arr, equals) {
var originalArr = arr.slice(0);
var i, len, j, val;
arr.length = 0;
for (i = 0, len = originalArr.length; i < len; ++i) {
val = originalArr[i];
if (!arrayContains(arr, val, equals)) {
arr.push(val);
}
}
}
function thingsEqual(thing1, thing2) {
return thing1.place === thing2.place
&& thing1.name === thing2.name;
}
removeDuplicates(things.thing, thingsEqual);
如果您可以等到所有相加之后再消除重复,则典型的方法是先对数组进行排序,然后消除重复。排序避免了在遍历数组时为每个元素扫描数组的 N * N 方法。
“消除重复”功能通常称为 unique 或 uniq。一些现有的实现可能会结合这两个步骤,例如,prototype's uniq
This post 几乎没有可以尝试的想法(有些想法要避免 :-))如果您的图书馆还没有!我个人认为这是最直接的:
function unique(a){
a.sort();
for(var i = 1; i < a.length; ){
if(a[i-1] == a[i]){
a.splice(i, 1);
} else {
i++;
}
}
return a;
}
// Provide your own comparison
function unique(a, compareFunc){
a.sort( compareFunc );
for(var i = 1; i < a.length; ){
if( compareFunc(a[i-1], a[i]) === 0){
a.splice(i, 1);
} else {
i++;
}
}
return a;
}
function(_a,_b){return _a.a===_b.a && _a.b===_b.b;}
,那么数组将不会被排序。
我认为最好的方法是使用 reduce 和 Map object。 这是单行解决方案。
const data = [ {id: 1, name: 'David'}, {id: 2, name: 'Mark'}, {id: 2, name: 'Lora'}, {id: 4, name: 'Tyler' }, {id: 4, name: 'Donald'}, {id: 5, name: 'Adrian'}, {id: 6, name: 'Michael'} ] const uniqueData = [...data.reduce(( map, obj) => map.set(obj.id, obj), new Map()).values()]; console.log(uniqueData) /* in `map.set(obj.id, obj)` 'obj.id' 是关键。 (别担心。我们将使用 .values() 方法仅获取值)'obj' 是整个对象。 */
一个带地图的班轮(高性能,不保留订单)
在数组 arr
中查找唯一的 id
。
const arrUniq = [...new Map(arr.map(v => [v.id, v])).values()]
如果订单很重要,请查看带有过滤器的解决方案:Solution with filter
数组 arr
中的多个属性(place
和 name
)唯一
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()
该死的,孩子们,让我们粉碎这件事,我们为什么不呢?
让 uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{ id:'d'}];让过滤 = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));控制台.log(过滤); // 预期:[{id:'a'},{id:'b'},{id:'c'},{id:'d'}];
id
。该问题需要整个对象在所有字段(例如 place
和 name
)中都是唯一的
place
和 name
。阅读此线程的任何人都在寻找一种对对象列表进行重复数据删除的最佳方法,这是一种紧凑的方法。
再添加一个到列表中。将 ES6 和 Array.reduce
与 Array.find
一起使用。
在此示例中,基于 guid
属性过滤对象。
let filtered = array.reduce((accumulator, current) => {
if (! accumulator.find(({guid}) => guid === current.guid)) {
accumulator.push(current);
}
return accumulator;
}, []);
扩展这个以允许选择一个属性并将其压缩成一个衬里:
const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);
要使用它,请将对象数组和您希望重复数据删除的键的名称作为字符串值传递:
const result = uniqify(myArrayOfObjects, 'guid')
您还可以使用 Map
:
const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());
完整样本:
const things = new Object();
things.thing = new Array();
things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});
const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());
console.log(JSON.stringify(dedupThings, null, 4));
结果:
[
{
"place": "here",
"name": "stuff"
},
{
"place": "there",
"name": "morestuff"
}
]
TypeScript 解决方案
这将删除重复的对象并保留对象的类型。
function removeDuplicateObjects(array: any[]) {
return [...new Set(array.map(s => JSON.stringify(s)))]
.map(s => JSON.parse(s));
}
any
完全违背了 TypeScript 的目的
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
让 myData = [{place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"}];让 q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];控制台日志(q)
使用 ES6 和 new Map()
的单行代码。
// assign things.thing to myData
let myData = things.thing;
[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];
细节:-
在数据列表上执行 .map() 并将每个单独的对象转换为 [key, value] 对数组(长度 = 2),第一个元素(键)将是对象的字符串化版本,第二个(值)将是一个对象本身。将上面创建的数组列表添加到 new Map() 将使键作为字符串化对象,并且任何相同的键添加都将导致覆盖已经存在的键。使用 .values() 将为 MapIterator 提供 Map 中的所有值(在我们的例子中为 obj )最后,传播 ... 运算符以提供具有上述步骤的值的新 Array。
const things = [ {place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"} ]; const filteredArr = things.reduce((thing, current) => { const x = thing.find(item => item.place === current.place); if (!x) { return thing.concat([current] ); } else { 返回东西; } }, []); console.log(filteredArr)
通过 Set
对象解决方案 |根据数据类型
常量看见 = 新的 Set(); const things = [ {place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"} ]; const filtersArr = things.filter(el => { const duplicate = seen.has(el.place); seen.add(el.place); return !duplicate; }); console.log(filteredArr)
Set
对象特征
Set Object 中的每个值都必须是唯一的,将检查值是否相等
Set 对象的目的是根据数据类型存储唯一值,无论是原始值还是对象引用。它有四个非常有用的实例方法 add
、clear
、has
& delete
。
独特和数据类型功能:..
add
方法
它默认将唯一数据推送到集合中也保留数据类型..这意味着它可以防止将重复项推送到集合中,它也会默认检查数据类型...
has
方法
有时需要检查数据项是否存在于集合中。它是收集唯一 ID 或项目和数据类型的便捷方法。
delete
方法
它将通过识别数据类型从集合中删除特定项目..
clear
方法
它将从一个特定变量中删除所有集合项并设置为空对象
Set
对象也有 迭代方法 &更多功能..
从这里开始阅读: Set - JavaScript | MDN
removeDuplicates()
接收一个对象数组并返回一个没有任何重复对象的新数组(基于 id 属性)。
const allTests = [
{name: 'Test1', id: '1'},
{name: 'Test3', id: '3'},
{name: 'Test2', id: '2'},
{name: 'Test2', id: '2'},
{name: 'Test3', id: '3'}
];
function removeDuplicates(array) {
let uniq = {};
return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}
removeDuplicates(allTests);
预期结果:
[
{name: 'Test1', id: '1'},
{name: 'Test3', id: '3'},
{name: 'Test2', id: '2'}
];
首先,我们将变量 uniq 的值设置为一个空对象。
接下来,我们过滤对象数组。 Filter 创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。
return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
上面,我们使用了 && 的短路功能。如果 && 左侧的值为真,则返回 && 右侧的值。如果左侧为假,则返回 && 左侧的内容。
对于每个对象(obj),我们检查 uniq 是否有一个名为 obj.id 值的属性(在这种情况下,在第一次迭代时,它将检查属性“1”。)我们想要它返回的相反(要么为真)或假)这就是为什么我们使用!在 !uniq[obj.id]
。如果 uniq 已经有 id 属性,它返回 true ,结果为 false (!) 告诉过滤器函数不要添加那个 obj。但是,如果它没有找到 obj.id 属性,它会返回 false,然后计算结果为 true (!) 并返回 && 右侧的所有内容,或者 (uniq[obj.id] = true)。这是一个真值,告诉 filter 方法将该 obj 添加到返回的数组中,它还将属性 {1: true} 添加到 uniq。这确保不会再次添加具有相同 id 的任何其他 obj 实例。
这种方式对我很有效:
function arrayUnique(arr, uniqueKey) {
const flagList = new Set()
return arr.filter(function(item) {
if (!flagList.has(item[uniqueKey])) {
flagList.add(item[uniqueKey])
return true
}
})
}
const data = [
{
name: 'Kyle',
occupation: 'Fashion Designer'
},
{
name: 'Kyle',
occupation: 'Fashion Designer'
},
{
name: 'Emily',
occupation: 'Web Designer'
},
{
name: 'Melissa',
occupation: 'Fashion Designer'
},
{
name: 'Tom',
occupation: 'Web Developer'
},
{
name: 'Tom',
occupation: 'Web Developer'
}
]
console.table(arrayUnique(data, 'name'))// work well
打印出
┌─────────┬───────────┬────────────────────┐
│ (index) │ name │ occupation │
├─────────┼───────────┼────────────────────┤
│ 0 │ 'Kyle' │ 'Fashion Designer' │
│ 1 │ 'Emily' │ 'Web Designer' │
│ 2 │ 'Melissa' │ 'Fashion Designer' │
│ 3 │ 'Tom' │ 'Web Developer' │
└─────────┴───────────┴────────────────────┘
ES5:
function arrayUnique(arr, uniqueKey) {
const flagList = []
return arr.filter(function(item) {
if (flagList.indexOf(item[uniqueKey]) === -1) {
flagList.push(item[uniqueKey])
return true
}
})
}
这两种方式更简单,更容易理解。
这是 ES6 的解决方案,您只想保留最后一项。该解决方案功能强大且符合 Airbnb 风格。
const things = {
thing: [
{ place: 'here', name: 'stuff' },
{ place: 'there', name: 'morestuff1' },
{ place: 'there', name: 'morestuff2' },
],
};
const removeDuplicates = (array, key) => {
return array.reduce((arr, item) => {
const removed = arr.filter(i => i[key] !== item[key]);
return [...removed, item];
}, []);
};
console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]
为懒惰的 Typescript 开发人员提供快速(更少的运行时间)和类型安全的答案:
export const uniqueBy = <T>( uniqueKey: keyof T, objects: T[]): T[] => {
const ids = objects.map(object => object[uniqueKey]);
return objects.filter((object, index) => !ids.includes(object[uniqueKey], index + 1));
}
uniqueKey
应该是 keyof T
而不是 string
以使其更精确。
我知道这个问题已经有很多答案了,但请耐心等待......
数组中的某些对象可能具有您不感兴趣的附加属性,或者您只想查找唯一对象,仅考虑属性的子集。
考虑下面的数组。假设您想仅考虑 propOne
和 propTwo
来查找此数组中的唯一对象,并忽略可能存在的任何其他属性。
预期结果应仅包括第一个和最后一个对象。所以这里是代码:
const array = [{ propOne: 'a', propTwo: 'b', propThree: '我没有参与这个...' }, { propOne: 'a', propTwo: 'b', someOtherProperty: '没有人关心这个...' }, { propOne: 'x', propTwo: 'y', yetAnotherJunk: '我真的一文不值', noOneHasThis: '我有没有人有的东西' }]; const uniques = [...new Set(array.map(x => JSON.stringify(((o) => ({ propOne: o.propOne, propTwo: o.propTwo }))(x)))) ] .map(JSON.parse); console.log(唯一);
array
中的第一个和第二个对象成为 uniques
中的一个。现在该对象应该包含来自 array[0]
的 propThree
,还是来自 array[1]
的 someOtherProperty
,或两者兼有,还是其他?只要我们确切地知道在这种情况下该怎么做,您所要求的肯定是可行的。
(({ propOne, propTwo }) => ({ propOne, propTwo }))(x)
?
另一种选择是创建一个自定义 indexOf 函数,该函数比较您为每个对象选择的属性的值,并将其包装在一个 reduce 函数中。
var uniq = redundant_array.reduce(function(a,b){
function indexOfProperty (a, b){
for (var i=0;i<a.length;i++){
if(a[i].property == b.property){
return i;
}
}
return -1;
}
if (indexOfProperty(a,b) < 0 ) a.push(b);
return a;
},[]);
lodash.isequal
npm package 作为轻量级对象比较器配对,以执行独特的数组过滤......例如不同的对象数组。只需换入 if (_.isEqual(a[i], b)) {
而不是查看 @ 单个属性
在这里,我找到了一个使用 reduce 方法从对象数组中删除重复项的简单解决方案。我正在根据对象的位置键过滤元素
const med = [ {name:'name1',位置:'left'},{name:'name2',位置:'right'},{name:'name3',位置:'left'},{name:' name4',位置:'right'},{name:'name5',位置:'left'},{name:'name6',位置:'left1'}] const arr = []; med.reduce((acc, curr) => { if(acc.indexOf(curr.position) === -1) { acc.push(curr.position); arr.push(curr); } 返回 acc; } , []) 控制台.log(arr)
继续探索 ES6 从对象数组中删除重复项的方法:将 Array.prototype.filter
的 thisArg
参数设置为 new Set
提供了一个不错的选择:
const things = [ {place:"here",name:"stuff"}, {place:"there",name:"morestuff"}, {place:"there",name:"morestuff"} ]; const filters = things.filter(function({place, name}) { const key =`${place}${name}`; return !this.has(key) && this.add(key); }, new Set );控制台.log(过滤);
但是,它不适用于箭头函数 () =>
,因为 this
绑定到它们的词法范围。
things.thing = things.thing.filter((thing, index, self) => self.findIndex(t => t.place === thing.place && t.name === thing.name) === index)
const uniqueArray = arrayOfObjects.filter((object,index) => index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object)));
jsfiddle.net/x9ku0p7L/28