我试图从这个 json 中删除重复的条目,但它只返回一个对象,我不明白我哪里出错了。
代码如下。
// exemplary array of objects (id 'NewLive' occurs twice)
var arr = [
{"jobcodeid":{"S":"Etc_new"}},
{"jobcodeid":{"S":"NewLive"}},
{"jobcodeid":{"S":"NewLiveVid"}},
{"jobcodeid":{"S":"New_Live"}},
{"jobcodeid":{"S":"New_Live_Vid"}},
{"jobcodeid":{"S":"Newest"}},
{"jobcodeid":{"S":"NewestLive"}},
{"jobcodeid":{"S":"NewestLiveVid"}},
{"jobcodeid":{"S":"Very_New_Vid"}},
{"jobcodeid":{"S":"Etc_new"}},
{"jobcodeid":{"S":"NewLive"}},
{"jobcodeid":{"S":"NewLiveVid"}},
{"jobcodeid":{"S":"New_Live"}},
{"jobcodeid":{"S":"New_Live_Vid"}},
{"jobcodeid":{"S":"Newest"}},
{"jobcodeid":{"S":"NewestLive"}},
{"jobcodeid":{"S":"NewestLiveVid"}},
{"jobcodeid":{"S":"Very_New_Vid"}}
],
obj = {}, new_arr = [];
// in the end the last unique object will be considered
arr.forEach(function(v){
obj[v['id']] = v;
console.log(JSON.stringify(new_arr));
});
new_arr = Object.keys(obj).map(function(id) { return obj[id]; });
console.log(JSON.stringify(new_arr));
我也附上了 codepen。
最佳答案
您的代码返回单个元素的原因是因为您正在使用 v['id']
但对象上没有 id
属性,因此自始至终您正在一遍又一遍地设置 obj[undefined]
的循环。
尽管在您的 jsfiddle 代码中这看起来是正确的并且代码似乎按预期工作。
如果有人遇到这个问题是想了解如何从 javascript 中的数组中删除重复项,这里有几个选项:
经典方式:好旧的 for 循环
这基本上是您使用的解决方案,遍历数组,检查键是否已添加到结果数组中,如果不存在,则将元素添加到结果中。
示例:
const result = [];
const knownIDs = new Set();
for (const item of input) {
if (!knownIDs.has(item.jobcodeid.S)) {
result.push(item);
knownIDs.add(item.jobcodeid.S);
}
}
前往 map 并返回
要过滤重复项,您可以将元素转换为 Map
键 -> 值,然后转换回数组。这是有效的,因为键在 Map
中是唯一的,并且重复项将被自动消除。这种方法的主要优点是,由于代码简单,错误较少。
console.log(
Array.from(
new Map(
input.map(i => [i.jobcodeid.S, i])
).values()
)
)
过滤和设置
另一种选择是使用Set
来记录已知的id 和filter
删除具有已知 ID 的项目。这种方法的优点是它可能更容易阅读,因为意图是明确的。此外,这比转换为 Map
并返回的性能更高。
const knownKeys = new Set();
console.log(
input.filter(i => {
if (!knownKeys.has(i.jobcodeid.S)) {
knownKeys.add(i.jobcodeid.S);
return true;
}
})
);
查看它们的实际效果:
const input = [{"jobcodeid":{"S":"Etc_new"}},{"jobcodeid":{"S":"NewLive"}},{"jobcodeid":{"S":"NewLiveVid"}},{"jobcodeid":{"S":"New_Live"}},{"jobcodeid":{"S":"New_Live_Vid"}},{"jobcodeid":{"S":"Newest"}},{"jobcodeid":{"S":"NewestLive"}},{"jobcodeid":{"S":"NewestLiveVid"}},{"jobcodeid":{"S":"Very_New_Vid"}},{"jobcodeid":{"S":"Etc_new"}},{"jobcodeid":{"S":"NewLive"}},{"jobcodeid":{"S":"NewLiveVid"}},{"jobcodeid":{"S":"New_Live"}},{"jobcodeid":{"S":"New_Live_Vid"}},{"jobcodeid":{"S":"Newest"}},{"jobcodeid":{"S":"NewestLive"}},{"jobcodeid":{"S":"NewestLiveVid"}},{"jobcodeid":{"S":"Very_New_Vid"}}];
// Classic for loop
const result = [];
const knownIDs = new Set();
for (const item of input) {
if (!knownIDs.has(item.jobcodeid.S)) {
result.push(item);
knownIDs.add(item.jobcodeid.S);
}
}
console.log(result.map(r => r.jobcodeid.S));
// To Map and back
console.log(
Array.from(
new Map(
input.map(i => [i.jobcodeid.S, i])
).values()
)
)
// filter and set
const knownKeys = new Set();
console.log(
input.filter(i => {
if (!knownKeys.has(i.jobcodeid.S)) {
knownKeys.add(i.jobcodeid.S);
return true;
}
})
);
作为记录,我在公认的解决方案、我的解决方案和 Jacques' answer 的性能改进上运行了基准测试
accepted solution x 1,892,585 ops/sec ±3.48% (89 runs sampled)
Map and back x 495,116 ops/sec ±2.27% (90 runs sampled)
Set and filter x 1,600,833 ops/sec ±1.98% (90 runs sampled)
Jacques x 2,110,510 ops/sec ±0.98% (92 runs sampled)
Fastest is Jacques
如您所见,Jacques' solution确实快了一倍,所以如果你的目标是过滤巨大的数组或者如果性能是关键,你绝对应该选择它!
关于javascript - 从数组中删除重复项只返回一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53220284/