从数组中删除重复项仅返回一个对象

时间:2018-11-09 05:22:54

标签: javascript arrays node.js json

我正在尝试从此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。

https://codepen.io/anon/pen/oQXJWK

5 个答案:

答案 0 :(得分:4)

您的代码返回单个元素的原因是因为您使用的是v['id'],但是对象上没有id属性,因此在整个循环中,您将obj[undefined]设置为以上。

尽管在您的jsfiddle代码中,这看起来是正确的,但代码似乎可以正常工作。

如果有人遇到此问题以了解如何从JavaScript中的数组中删除重复项,请使用以下几种选择:

经典方式:循环不错

从本质上讲,这是您使用的解决方案,遍历数组,检查键是否已添加到结果数组,如果不存在,则将元素添加到结果中。

示例:

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中是唯一的,并且重复项将自动消除。这种方法的主要优点是,由于代码的简单性,它将减少错误。

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的确是两倍的速度,因此,如果您打算过滤大型数组或性能很关键,则绝对应该选择它!

答案 1 :(得分:1)

首先,您必须使用obj[v['jobcodeid']] = v;而不是obj[v['id']] = v;

但是由于v[jobcodeid]是一个对象,因此js会将其转换为字符串,即[object Object],并且最终数组中将只有一个元素。

// 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['jobcodeid']] = v;
});
new_arr = Object.keys(obj).map(function(id) { return obj[id]; });

console.log(JSON.stringify(new_arr));

您应该使用v.jobcodeid.S作为对象的键。

// 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.jobcodeid.S] = v;
});
new_arr = Object.keys(obj).map(function(id) { return obj[id]; });

console.log(JSON.stringify(new_arr));

答案 2 :(得分:1)

发布答案以显示另一种更高效率的方法。

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
for (const job of arr) {
	if (!obj[job.jobcodeid.S]) {
		obj[job.jobcodeid.S] = true;
		new_arr.push(job);
    }
}

console.log(JSON.stringify(new_arr));

此答案始终运行N次迭代。设置唯一值后在键之间循环时,它最多可以运行2N次迭代。 (从谈论大O /复杂性改为更清晰)

答案 3 :(得分:1)

您需要使用Set

const 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" } }
];

const uniqueItems = [...new Set(arr.map(i => i.jobcodeid.S))]

答案 4 :(得分:0)

也尝试一下。.解决此问题的另一种方法

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 = [];


arr.forEach(function(v){
    obj[v['id']] = v;

    for(var i=0;i< new_arr.length;i++){
      if(new_arr[i].jobcodeid.S == v.jobcodeid.S)       {
         return;
      }
    } 
      new_arr.push(v);     
});

console.log(new_arr);