在数组中查找重复对象的有效方法

时间:2018-01-03 08:26:50

标签: javascript arrays angular typescript unique

我正在使用angular4。我需要显示一个包含唯一值的列表。

访问API时,我得到一个数组,从那个数组我需要只显示唯一数据。我将以特定的时间间隔访问该API,并且只有在存在新数据时才需要更新列表。

response= [{"id":"0DRDCH03DR51GGJGJNP80F7XZ8","value":"36af1784bec4_566601260"},{"id":"0DRDCFYGM2CAHAXYK96BPT9RHV","value":"36af1784bec4_566601140"},...]

listData = [];
for(let data of response) {
    let tempValue = {id: '', time: ''};
    let value = data.value.split('_')
    if (value.length==2) {
        if(value[value.length-1].length==2) {
            tempValue.id = value[0];
            tempValue.time = value[1];
        }
        let isPresent = false;
        if(this.listData.length>0){
            for(let value of this.listData){
                if(value.time===tempValue.time){
                    isPresent = true;
                }
            }
        }
        if(!isPresent) {
            this.listData.push(tempValue);
        }
    }

    }

最终的listData

listData = [{id:'36af1784bec4', time: '566601140'},...]

上面的函数确实给了我一个唯一的listData数组。我尝试使用array.filternew Set但无法达到预期效果。

我想知道是否有一种有效的方法可以做到这一点。

6 个答案:

答案 0 :(得分:2)

您可以通过以下代码删除副本。

var obj = {};

for ( var i=0, len=response.length; i < len; i++ )
    obj[response[i]['id']] = response[i]; // if id Duplicate otherwise use value if the check on value.

response = new Array();
for ( var key in obj )
    response.push(obj[key]);

console.log(response); // listData 

修改

如果你想对你的道具进行全面检查,那么你可以选择这个

function removeDuplicates(myArr, prop) {
    return myArr.filter((obj, pos, arr) => {
        return arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos;
    });
}


console.log(removeDuplicates(response,['id','value'])); // for id or value use only 'id' or 'value' in second parameter.

答案 1 :(得分:1)

我认为这样做

for(let data of response) {
    if(!this.listData.find((ldata) => data.value.substring(data.value.lastIndexOf('_')+1) === ldata.time)) {
        let tempValue = {id: '', time: ''};
        let value = data.value.split('_')
        if (value.length==2) {
            if(value[value.length-1].length==2) {
                tempValue.id = value[0];
                tempValue.time = value[1];
            }
            this.listData.push(tempValue);
        }
    }
}

答案 2 :(得分:1)

您也可以通过JSON.stringify以下对象执行此操作:

let response = [{
  "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
  "value": "36af1784bec4_566601260"
}, {
  "id": "0DRDCFYGM2CAHAXYK96BPT9RHV",
  "value": "36af1784bec4_566601140"
}, {
  "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
  "value": "36af1784bec4_566601260"
}]

let o = response.reduce((acc, cv) => {
  if (!acc[JSON.stringify(cv)]) {
    acc[JSON.stringify(cv)] = true; //something non-falsy
  }
  return acc;
}, {});

let res = Object.keys(o).map(x => JSON.parse(x));
console.log(res);

修改 正如user3297291指出

  

可能有助于注意JSON.stringify({a:1,b:2})!== JSON.stringify({b:2,a:1})

因此,上述情况将失败。

更优化的解决方案是

let response = [{
  "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
  "value": "36af1784bec4_566601260"
}, {
  "id": "0DRDCFYGM2CAHAXYK96BPT9RHV",
  "value": "36af1784bec4_566601140"
}, {
  "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
  "value": "36af1784bec4_566601260"
}];

let o = response.reduce((acc, cv) => {
  if (!acc[cv.value]) {
    acc[cv.value] = true; //something non-falsy
  }
  return acc;
}, {});

let res = Object.keys(o).map(x => {
  let t = x.split('_');
  return {
    id: t[0],
    time: t[1]
  };
});
console.log(res);

答案 3 :(得分:1)

对于优化解决方案(仅循环一次,即O(n)) 使用object属性来检查属性是否已经添加,通过这种方式,您将避免循环以查找是否已添加属性。

以下是示例解决方案

&#13;
&#13;
let response = [{
    "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
    "value": "36af1784bec4_566601260"
  }, {
    "id": "0DRDCH03DR51GGJGJNP80F7XZ8",
    "value": "36af1784bec4_566601260"
  }, {
    "id": "0DRDCFYGM2CAHAXYK96BPT9RHV",
    "value": "36af1784bec4_566601140"
  }],
  listData = [],
  tempObj = {};
for (let data of response) {
    let value = data.value.split('_');
  if (!tempObj.hasOwnProperty(value[1])) {
    tempObj[data.value[1]] = "";
    listData.push({
      id: value[0],
      time: value[1]
    });
  }
}

console.log(listData);
&#13;
&#13;
&#13;

更新:根据评论,仅检查重复的时间值

答案 4 :(得分:0)

您可以使用map来收集ID,然后使用filter删除重复项:

const response= [{"id":"0DRDCH03DR51GGJGJNP80F7XZ8","value":"36af1784bec4_566601260"},{"id":"0DRDCFYGM2CAHAXYK96BPT9RHV","value":"36af1784bec4_566601140"}];

const ids = response.map(it => it.value.split('_')[0]).filter((it, i, arr) => i === arr.indexOf(it))

console.log(ids);

或使用reduce

const response= [{"id":"0DRDCH03DR51GGJGJNP80F7XZ8","value":"36af1784bec4_566601260"},{"id":"0DRDCFYGM2CAHAXYK96BPT9RHV","value":"36af1784bec4_566601140"}];

const ids = response.reduce((acc, it) => {
  const id = it.value.split('_')[0];
  return acc.includes(id) ? acc : [...acc, id];
}, []);

console.log(ids);

答案 5 :(得分:0)

JavaScript的最新版本允许对对象结构的依赖保持不变...因此,我们现在可以依靠对两个字符串进行字符串化和比较:

arr = [{object}, {object2}, {etc...}]
test = JSON.stringify(obj);

for ( let i = 0, j = arr.length; i < j; i++ ) {
  let testAgainst = JSON.stringify(arr[i]);
  if (test === testAgainst) { 
    console.log('matches');
  } else {
    console.log('no match');
  }
}

所以有一个对象数组:

  1. 对要测试的对象进行字符串化
  2. 循环遍历每个对象的字符串
  3. 比较两个

很有帮助,因为您不需要知道键名。它只适用于任何对象类型...

{{1}}

现在您将匹配两个字符串。如果我缺少什么,请发表评论。