Tra*_*vis 306 javascript arrays object duplicates
我有一个包含对象数组的对象.
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"});
Run Code Online (Sandbox Code Playgroud)
我想知道从数组中删除重复对象的最佳方法是什么.所以,例如,事情会变成......
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
Run Code Online (Sandbox Code Playgroud)
Eyd*_*ian 348
有些es6魔法怎么样?
things.thing = things.thing.filter((thing, index, self) =>
index === self.findIndex((t) => (
t.place === thing.place && t.name === thing.name
))
)
Run Code Online (Sandbox Code Playgroud)
对于前端,这可能有点早到实现,因为许多使用的浏览器仍然不支持es6功能
aef*_*fxx 143
让我们看看...一个原始的:
var obj = {};
for ( var i=0, len=things.thing.length; i < len; i++ )
obj[things.thing[i]['place']] = things.thing[i];
things.thing = new Array();
for ( var key in obj )
things.thing.push(obj[key]);
Run Code Online (Sandbox Code Playgroud)
好吧,我认为应该这样做.看看,特拉维斯.
编辑
编辑代码以正确引用__CODE__(以前__CODE__)属性.
leo*_*ess 106
这是一个简短的 ES6 方法,其运行时间比已经存在的 65+ 个答案更好:
let ids = array.map(o => o.id)
let filtered = array.filter(({id}, index) => !ids.includes(id, index + 1))
Run Code Online (Sandbox Code Playgroud)
let ids = array.map(o => o.id)
let filtered = array.filter(({id}, index) => !ids.includes(id, index + 1))
Run Code Online (Sandbox Code Playgroud)
Array.filter()通过检查先前映射的 id-array 是否包含当前 id 来删除所有重复对象({id}将对象仅分解为它的 id)。要仅过滤出实际副本,它是使用Array.includes()的第二参数fromIndex与index + 1这将忽略当前对象和所有先前的。
由于filter回调方法的每次迭代只会搜索从当前索引 + 1 开始的数组,这也大大减少了运行时间,因为只有先前未过滤的对象才会被检查。
这显然也适用于任何其他未被调用的键,id甚至多个或所有键。
amb*_*odi 91
如果您可以使用Javascript库,例如下划线或lodash,我建议您查看_.uniq其库中的函数.来自lodash:
_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
Run Code Online (Sandbox Code Playgroud)
基本上,你传入的数组在这里是一个对象文字,你传入要在原始数据数组中删除重复项的属性,如下所示:
var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name');
Run Code Online (Sandbox Code Playgroud)
更新:Lodash现在也推出了一款.uniqBy.
Jam*_*ard 69
我有完全相同的要求,根据单个字段上的重复项删除数组中的重复对象.我在这里找到了代码:Javascript:从对象数组中删除重复项
所以在我的例子中,我正在从数组中删除任何具有重复的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));
Run Code Online (Sandbox Code Playgroud)
结果:
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"}]
Run Code Online (Sandbox Code Playgroud)
chi*_*ens 37
一张带地图的班轮(高性能,不保留顺序)
查找id数组中唯一的arr。
const arrUniq = [...new Map(arr.map(v => [v.id, v])).values()]
Run Code Online (Sandbox Code Playgroud)
如果顺序很重要,请查看带过滤器的解决方案:带过滤器的解决方案
数组中多个属性 (place和) 唯一namearr
const arrUniq = [...new Map(arr.map(v => [JSON.stringify([v.place,v.name]), v])).values()]
Run Code Online (Sandbox Code Playgroud)
数组中所有属性都是唯一的arr
const arrUniq = [...new Map(arr.map(v => [JSON.stringify(v), v])).values()]
Run Code Online (Sandbox Code Playgroud)
保留数组中第一次出现的位置arr
const arrUniq = [...new Map(arr.slice().reverse().map(v => [v.id, v])).values()].reverse()
Run Code Online (Sandbox Code Playgroud)
Mμ.*_*Mμ. 34
一个班轮使用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"});
// assign things.thing to myData for brevity
var myData = things.thing;
things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);
console.log(things.thing)Run Code Online (Sandbox Code Playgroud)
说明:
new Set(myData.map(JSON.stringify))使用字符串化的myData元素创建一个Set对象.小智 25
如果您只需要通过对象的一个字段进行比较,则可以使用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');
Run Code Online (Sandbox Code Playgroud)
mac*_*llt 22
如果您可以等到所有添加之后消除重复项,则典型的方法是首先对数组进行排序,然后消除重复项.排序避免了在遍历它们时扫描每个元素的数组的N*N方法.
"消除重复"功能通常称为unique或uniq.一些现有实现可以组合这两个步骤,例如原型的uniq
如果您的图书馆还没有,那么这篇文章几乎没有想过尝试(有些要避免:-))!我个人觉得这个最直接:
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;
}
Run Code Online (Sandbox Code Playgroud)
sra*_*nji 20
一个班轮在这里
let arr = [
{id:1,name:"sravan ganji"},
{id:2,name:"anu"},
{id:4,name:"mammu"},
{id:3,name:"sanju"},
{id:3,name:"ram"},
];
console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))Run Code Online (Sandbox Code Playgroud)
аle*_*kyі 19
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)Run Code Online (Sandbox Code Playgroud)
chi*_*ens 16
ES6 +的最短衬管
id在数组中查找唯一的。
arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)
Run Code Online (Sandbox Code Playgroud)
通过多个属性(place和name)唯一
arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)
Run Code Online (Sandbox Code Playgroud)
Unique by all properties (This will be slow for large arrays)
arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
Run Code Online (Sandbox Code Playgroud)
Keep the last occurrence. Add slice and reverse to beginning and reverse again in the end.
arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()
Run Code Online (Sandbox Code Playgroud)
Tim*_*own 14
更新
我现在已经正确地阅读了这个问题.这是执行此操作的一般方法:传入一个函数,该函数测试数组的两个元素是否相等.在这种情况下,它会比较被比较的两个对象的值name和place属性.
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 (!arr.some(function(item) { return thingsEqual(item, val); })) {
arr.push(val);
}
}
}
function 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"}
];
removeDuplicates(things, thingsEqual);
console.log(things);Run Code Online (Sandbox Code Playgroud)
Pet*_*e B 13
要再向列表中添加一个.使用ES6并Array.reduce用Array.find.
在此示例中,基于guid属性过滤对象.
let filtered = array.reduce((accumulator, current) => {
if (! accumulator.find(({guid}) => guid === current.guid)) {
accumulator.push(current);
}
return accumulator;
}, []);
Run Code Online (Sandbox Code Playgroud)
扩展这个以允许选择属性并将其压缩成一个衬里:
const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);
Run Code Online (Sandbox Code Playgroud)
要使用它,请传递一个对象数组以及您希望作为字符串值进行重复数据删除的键的名称:
const result = uniqify(myArrayOfObjects, 'guid')
Run Code Online (Sandbox Code Playgroud)
dgk*_*nca 13
我认为最好的方法是使用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' is key. (don't worry. we'll get only values using the .values() method)
'obj' is whole object.
*/Run Code Online (Sandbox Code Playgroud)
Pra*_*eek 11
你也可以使用Map:
const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());
Run Code Online (Sandbox Code Playgroud)
完整样本:
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));
Run Code Online (Sandbox Code Playgroud)
结果:
[
{
"place": "here",
"name": "stuff"
},
{
"place": "there",
"name": "morestuff"
}
]
Run Code Online (Sandbox Code Playgroud)
V. *_*bor 11
在一行中使用ES6,您可以通过按键获得对象的唯一列表:
const unique = [...new Map(arr.map(item => [item[key], item])).values()]
Run Code Online (Sandbox Code Playgroud)
可以将其放入函数中,并在以下示例中使用:
const unique = [...new Map(arr.map(item => [item[key], item])).values()]
Run Code Online (Sandbox Code Playgroud)
Mas*_*iri 11
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));
}
Run Code Online (Sandbox Code Playgroud)
Cli*_*all 10
Dang,孩子们,让我们粉碎这件事,为什么不呢?
let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];Run Code Online (Sandbox Code Playgroud)
小智 10
TypeScript解决方案
这将删除重复的对象,并保留对象的类型。
function removeDuplicateObjects(array: any[]) {
return [...new Set(array.map(s => JSON.stringify(s)))]
.map(s => JSON.parse(s));
}
Run Code Online (Sandbox Code Playgroud)
小智 10
如果数组包含对象,那么您可以使用它来删除重复的
const persons= [
{ id: 1, name: 'John',phone:'23' },
{ id: 2, name: 'Jane',phone:'23'},
{ id: 1, name: 'Johnny',phone:'56' },
{ id: 4, name: 'Alice',phone:'67' },
];
const unique = [...new Map(persons.map((m) => [m.id, m])).values()];
Run Code Online (Sandbox Code Playgroud)
如果在phone的基础上去重,只需将m.id替换为m.phone即可
const unique = [...new Map(persons.map((m) => [m.phone, m])).values()];
Run Code Online (Sandbox Code Playgroud)
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 {
return thing;
}
}, []);
console.log(filteredArr)Run Code Online (Sandbox Code Playgroud)
通过Set对象解决方案| 根据数据类型
const seen = new Set();
const things = [
{place:"here",name:"stuff"},
{place:"there",name:"morestuff"},
{place:"there",name:"morestuff"}
];
const filteredArr = things.filter(el => {
const duplicate = seen.has(el.place);
seen.add(el.place);
return !duplicate;
});
console.log(filteredArr)Run Code Online (Sandbox Code Playgroud)
Set 对象特征
Set Object 中的每个值都必须是唯一的,将检查值是否相等
Set 对象的目的是根据数据类型存储唯一值,无论是原始值还是对象引用。它有四个非常有用的实例方法add, clear, has& delete。
唯一和数据类型功能:...
add方法
默认情况下,它会将唯一数据推送到集合中并保留数据类型..这意味着它可以防止将重复项推送到集合中,并且默认情况下它还会检查数据类型...
has 方法
有时需要检查数据项是否存在于集合中,并且 . 这是集合确定唯一 id 或项目和数据类型的方便方法..
delete 方法
它将通过识别数据类型从集合中删除特定项目..
clear 方法
它将从一个特定变量中删除所有集合项并设置为空对象
Set对象也有迭代方法和更多功能..
更好地从这里阅读: 设置 - JavaScript | MDN
这种方式对我很有效:
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
Run Code Online (Sandbox Code Playgroud)
打印
????????????????????????????????????????????
? (index) ? name ? occupation ?
????????????????????????????????????????????
? 0 ? 'Kyle' ? 'Fashion Designer' ?
? 1 ? 'Emily' ? 'Web Designer' ?
? 2 ? 'Melissa' ? 'Fashion Designer' ?
? 3 ? 'Tom' ? 'Web Developer' ?
????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
ES5:
function arrayUnique(arr, uniqueKey) {
const flagList = []
return arr.filter(function(item) {
if (flagList.indexOf(item[uniqueKey]) === -1) {
flagList.push(item[uniqueKey])
return true
}
})
}
Run Code Online (Sandbox Code Playgroud)
这两种方式更简单,更容易理解。
小智 6
另一种选择是创建一个自定义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;
},[]);
Run Code Online (Sandbox Code Playgroud)
考虑到 lodash.uniqWith
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
Run Code Online (Sandbox Code Playgroud)
小智 6
这是 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' }]
Run Code Online (Sandbox Code Playgroud)
我知道这个问题已经有很多答案了,但请耐心等待...
数组中的某些对象可能具有您不感兴趣的其他属性,或者您只想查找仅考虑属性子集的唯一对象。
考虑下面的数组。假设您只想在此数组中查找唯一对象propOne和propTwo,并忽略可能存在的任何其他属性。
预期结果应仅包括第一个和最后一个对象。所以这里是代码:
const array = [{
propOne: 'a',
propTwo: 'b',
propThree: 'I have no part in this...'
},
{
propOne: 'a',
propTwo: 'b',
someOtherProperty: 'no one cares about this...'
},
{
propOne: 'x',
propTwo: 'y',
yetAnotherJunk: 'I am valueless really',
noOneHasThis: 'I have something no one has'
}];
const uniques = [...new Set(
array.map(x => JSON.stringify(((o) => ({
propOne: o.propOne,
propTwo: o.propTwo
}))(x))))
].map(JSON.parse);
console.log(uniques);Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
预期结果:
[
{name: 'Test1', id: '1'},
{name: 'Test3', id: '3'},
{name: 'Test2', id: '2'}
];
Run Code Online (Sandbox Code Playgroud)
首先,我们将变量uniq的值设置为一个空对象。
接下来,我们筛选对象数组。筛选器会创建一个新数组,其中包含所有通过提供的功能实现的测试的元素。
return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
Run Code Online (Sandbox Code Playgroud)
上面,我们使用&&的短路功能。如果&&的左侧求值为true,则返回&&右侧的值。如果左侧为假,则返回&&左侧的内容。
对于每个object(obj),我们都会在uniq中检查名为obj.id的值的属性(在这种情况下,在第一次迭代中它将检查属性'1'。)我们想要返回的结果与之相反(或者为true或false),这就是我们使用!的原因 在!uniq [obj.id]中。如果uniq已经具有id属性,则返回true,结果为false(!),告诉过滤器函数不要添加该obj。但是,如果找不到obj.id属性,它将返回false,然后求值为true(!),并返回&&或(uniq [obj.id] = true)右边的所有内容。这是一个真实值,它告诉filter方法将该obj添加到返回的数组中,并且还将属性{1:true}添加到uniq中。这样可以确保不会再添加任何其他具有相同ID的obj实例。
let myData = [{place:"here",name:"stuff"},
{place:"there",name:"morestuff"},
{place:"there",name:"morestuff"}];
let q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];
console.log(q)Run Code Online (Sandbox Code Playgroud)
使用ES6和的单线new Map()。
// assign things.thing to myData
let myData = things.thing;
[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];
Run Code Online (Sandbox Code Playgroud)
细节:-
.map()的数据列表和每个单独的对象转换成[key, value]一对阵列(长度= 2),所述第一元件(键)将是stringified所述对象的版本和第二(值)将是一个object本身。new Map()会将键作为stringified对象,并且添加任何相同的键都将导致覆盖已经存在的键。.values()将为MapIterator提供Map中的所有值(obj在我们的示例中)spread ...操作员使用上述步骤中的值为新数组赋值。