从JSON数组中删除重复的对象

我有一个数组,看起来像这样:

var standardsList = [ {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Geometry"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Orders of Operation"}, {"Grade": "Math 2", "Domain": "Geometry"}, {"Grade": "Math 2", "Domain": "Geometry"} ]; 

我需要删除重复的东西,所以这样的事情仍然存在:

 var standardsList = [ {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Geometry"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Orders of Operation"}, {"Grade": "Math 2", "Domain": "Geometry"} ]; 

我已经尝试安装underscore.js和使用._uniq,但似乎只有一个key:value对出现在对象的工作。 我似乎无法让它在多个键上工作。

当我尝试像这样的东西:

 var uniqueStandards = _.uniq(standardsList, function(item, key, Domain){ return item.Domain; }); 

我只获得前三个独特的价值(每个年级一个)。 但是我需要所有等级和领域的独特价值。 有没有一种简单的方法来将这两个键提供给_.uniq函数?

最终,我需要一个列表,每个独特的成绩作为标题和唯一的领域作为列表项传递到一个HTML页面。 我可能会犯这个错误,所以如果有一个更简单的方法来实现这个最终目标,我可以接受想法。

提前致谢!

编辑:得到一些好的回应,并想澄清我的最终目标是什么。 我试图创build一系列的HTML格式的列表:

 <div> <h3>Math K</h3> <li>Counting & Cardinality</li> <li>Geometry</li> </div> <div> <h3>Math 1</h3> <li>Counting & Cardinality</li> <li>Orders of Operation</li> </div> <div> <h3>Math 2</h3> <li>Geometry</li> </div> 

我原来的是创build一个数组,然后用$("#divid").append(array)将它推入页面上的<div>元素$("#divid").append(array)

最终,我需要一个列表,每个独特的成绩作为标题和唯一的领域作为列表项传递到一个HTML页面。 我可能会犯这个错误,所以如果有一个更简单的方法来实现这个最终目标,我可以接受想法。

所以你实际上并不需要你input的数组格式。

既然如此,我会用一个非常简单而有效的解决scheme直接去追求:

 var grades = {}; standardsList.forEach( function( item ) { var grade = grades[item.Grade] = grades[item.Grade] || {}; grade[item.Domain] = true; }); console.log( JSON.stringify( grades, null, 4 ) ); 

得到的grades对象是:

 { "Math K": { "Counting & Cardinality": true, "Geometry": true }, "Math 1": { "Counting & Cardinality": true, "Orders of Operation": true }, "Math 2": { "Geometry": true } } 

这种方法有一个有趣的地方是速度非常快。 请注意,它只能通过input数组进行一次传递,而不像其他需要多次传递的解决scheme(不pipe您是自己编写它们还是_.uniq()为您执行)。 对于less数项目来说,这并不重要,但对于大型列表,请记住这一点。

通过这个对象,您现在拥有了运行任何代码或生成其他所需格式所需的一切。 例如,如果您确实需要您提到的确切数组输出格式,则可以使用:

 var outputList = []; for( var grade in grades ) { for( var domain in grades[grade] ) { outputList.push({ Grade: grade, Domain: domain }); } } JSON.stringify( outputList, null, 4 ); 

这将logging:

 [ { "Grade": "Math K", "Domain": "Counting & Cardinality" }, { "Grade": "Math K", "Domain": "Geometry" }, { "Grade": "Math 1", "Domain": "Counting & Cardinality" }, { "Grade": "Math 1", "Domain": "Orders of Operation" }, { "Grade": "Math 2", "Domain": "Geometry" } ] 

Rai在一个评论中询问这个代码行是如何工作的:

 var grade = grades[item.Grade] = grades[item.Grade] || {}; 

这是一个常见的习惯用于获取对象属性或提供一个默认值,如果属性丢失。 请注意, =赋值按照从右到左的顺序完成。 所以我们可以把它翻译成使用if语句和tempvariables:

 // Fetch grades[item.Grade] and save it in temp var temp = grades[item.Grade]; if( ! temp ) { // It was missing, so use an empty object as the default value temp = {}; } // Now save the result in grades[item.Grade] (in case it was missing) // and in grade grades[item.Grade] = temp; var grade = temp; 

您可能会注意到,如果grades[item.Grade]已经存在,我们就拿取刚刚提取的值并将其存回同一个属性。 当然,这是不必要的,如果你这样写代码,你可能不会这样做。 相反,你会简化它:

 var grade = grades[item.Grade]; if( ! grade ) { grade = grades[item.Grade] = {}; } 

这将是一个完全合理的方式来编写相同的代码,它也更有效率。 它也给你一个方法来做一个更具体的testing,而不是||真实性 成语依赖。 例如,而不是if( ! grade )你可能想使用if( grade === undefined )

 function arrUnique(arr) { var cleaned = []; arr.forEach(function(itm) { var unique = true; cleaned.forEach(function(itm2) { if (_.isEqual(itm, itm2)) unique = false; }); if (unique) cleaned.push(itm); }); return cleaned; } var standardsList = arrUnique(standardsList); 

小提琴

这将返回

 var standardsList = [ {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Geometry"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Orders of Operation"}, {"Grade": "Math 2", "Domain": "Geometry"} ]; 

你究竟在问什么?

Javascript解决scheme为您的情况:

 console.log(unique(standardsList)); function unique(obj){ var uniques=[]; var stringify={}; for(var i=0;i<obj.length;i++){ var keys=Object.keys(obj[i]); keys.sort(function(a,b) {return ab}); var str=''; for(var j=0;j<keys.length;j++){ str+= JSON.stringify(keys[j]); str+= JSON.stringify(obj[i][keys[j]]); } if(!stringify.hasOwnProperty(str)){ uniques.push(obj[i]); stringify[str]=true; } } return uniques; } 

振兴一个老问题,但我想在@ adeneo的答案上发表一个迭代。 这个答案是完全一般的,但是对于这个用例,它可能更有效率(我的机器上有几千个对象的数组很慢)。 如果您知道需要比较的对象的特定属性,则直接比较它们:

 var sl = standardsList; var out = []; for (var i = 0, l = sl.length; i < l; i++) { var unique = true; for (var j = 0, k = out.length; j < k; j++) { if ((sl[i].Grade === out[j].Grade) && (sl[i].Domain === out[j].Domain)) { unique = false; } } if (unique) { out.push(sl[i]); } } console.log(sl.length); // 10 console.log(out.length); // 5 

以下为我工作:

 _.uniq(standardsList, JSON.stringify) 

但是,对于很长的列表,这可能会很慢。

我需要做一些重复的JSON对象,所以我偶然发现这个页面。 不过,我使用的是简短的ES6解决scheme(不需要外部库),在Chrome开发工具代码片段中运行:

 const data = [ /* any list of objects */ ]; const set = new Set(data.map(item => JSON.stringify(item))); const dedup = [...set].map(item => JSON.parse(item)); console.log(`Removed ${data.length - dedup.length} elements`); console.log(dedup); 

我知道已经有很多答案了,但是为我的复杂json结构工作的最好的答案是:

 var arr =[{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RCSW","desc":"SOUTHWEST","code":"RCSW","level":0,"save":"RCSW : SOUTHWEST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""},{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RCSW","desc":"SOUTHWEST","code":"RCSW","level":0,"save":"RCSW : SOUTHWEST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""},{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""},{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RCSW","desc":"SOUTHWEST","code":"RCSW","level":0,"save":"RCSW : SOUTHWEST","attribute1":"","attribute2":""},{"State":"RWCW","desc":"WEST","code":"RWCW","level":0,"save":"RWCW : WEST","attribute1":"","attribute2":""},{"State":"RCNW","desc":"MIDWEST","code":"RCNW","level":0,"save":"RCNW : MIDWEST","attribute1":"","attribute2":""},{"State":"RCSW","desc":"SOUTHWEST","code":"RCSW","level":0,"save":"RCSW : SOUTHWEST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""},{"State":"RCNW","desc":"MIDWEST","code":"RCNW","level":0,"save":"RCNW : MIDWEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""},{"State":"RCNW","desc":"MIDWEST","code":"RCNW","level":0,"save":"RCNW : MIDWEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RCNW","desc":"MIDWEST","code":"RCNW","level":0,"save":"RCNW : MIDWEST","attribute1":"","attribute2":""},{"State":"RSCW","desc":"SOUTHEAST","code":"RSCW","level":0,"save":"RSCW : SOUTHEAST","attribute1":"","attribute2":""},{"State":"RECW","desc":"NORTHEAST","code":"RECW","level":0,"save":"RECW : NORTHEAST","attribute1":"","attribute2":""}] var clean= arr.filter((arr, index, self) => index === self.findIndex((t) => (t.save === arr.save && t.State === arr.State ))) console.log(clean); 

您可以直接尝试Chrome浏览器控制台并根据您的需要进行编辑。

我希望这可以帮助别人。

 var standardsList = [ {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Counting & Cardinality"}, {"Grade": "Math K", "Domain": "Geometry"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Counting & Cardinality"}, {"Grade": "Math 1", "Domain": "Orders of Operation"}, {"Grade": "Math 2", "Domain": "Geometry"}, {"Grade": "Math 2", "Domain": "Geometry"} ]; function uniqurArray(array){ var a = array.concat(); for(var i=0; i<a.length; i++) { for(var j=i+1; j<a.length; j++) { if(a[i].Grade === a[j].Grade){ a.splice(j--, 1); } } } return a; } uniqurArray(standardsList) // put this js in console and you get uniq object in array