如何根据对象属性值从对象数组中删除重复成员?

时间:2020-07-10 18:19:10

标签: javascript node.js arrays

数组如下:

var test = [
           {
            Time: new Date(1000), 
            psi:100.0
           }, 
           {
            Time: new Date(1000), 
            psi:200.0
           }, 
           {
            Time: new Date(2000), 
            psi:200.0
           }
          ]

函数看起来像(该函数是从某些在线资源中复制的,找不到确切的引用。)

function uniqTimetable(nums){
  console.log(nums); //log#1
  var length = nums.length;
  var count = 0;
  for (var i =0; i< length-1; i++){
    if (nums[count].Time.getTime() !== nums[i+1].Time.getTime()){
      count ++;
      nums[count] = nums[i+1];
    }
  }
  nums.length = count + 1;
  console.log(nums); // log #2
}

uniqTimetable(test);
console.log(test);// log #3 

有什么问题

  • 通过此行将一个对象复制到另一个数组成员nums[count] = nums[i+1]

  • 通过此行重新缩放数组长度nums.length = count + 1

对于electron / node.js,输出看起来有点奇怪。

在日志1中,它显示数组长度为2而不是3。该函数似乎出了点问题。欢迎任何建议。

谢谢。

3 个答案:

答案 0 :(得分:2)

如果我理解了这个问题,则可以通过一行功能解决它:

const test = [{
    Time: new Date(1000),
    psi: 100.0
  },
  {
    Time: new Date(1000),
    psi: 200.0
  },
  {
    Time: new Date(2000),
    psi: 200.0
  }
]

const unique = test.filter(({Time}, i, array) => 
  !array.find((item, j) => item.Time.getTime() === Time.getTime() && j > i));

console.log(unique);

(我认为psi不相关)

它使用findfilter数组的方法。

答案 1 :(得分:1)

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

使用javascript的filter函数,返回仅唯一元素的列表。

答案 2 :(得分:1)

我喜欢@Akin的答案!但是不幸的是,.indexOf()函数不适用于具有相同值的Date对象,因为每个对象仍然被认为是不同的,并且.indexOf()函数将始终找到Date对象本身的索引,而不会找到另一个“复制”。为了克服这个问题,我将Date对象转换回毫秒,然后再将其收集到数组(tst)中。在进入myArr.map(mapObj => mapObj[prop].getTime())函数之前,我先使用.filter进行此操作。

由于.getTime()方法仅适用于Date对象,因此保留属性prop作为参数是没有意义的。相反,我将.Time属性硬编码到了代码中。

编辑:

通过对+属性使用一元运算符.Time强制数字数据类型,可以省去.getTime()方法,该方法将隐式应用。

var test = [{Time: new Date(1000), psi:100.0}, 
            {Time: new Date(1000), psi:200.0}, 
            {Time: new Date(2000), psi:200.0}];

function Cars10m_remDups(myArr) {
  let tst=myArr.map(o=>+o.Time);
  return myArr.filter((o, i)=>tst.indexOf(+o.Time)===i);
}
// for comparison: --> will list all three objects!
function Akin_remDups(myArr, prop) {
  return myArr.filter((obj, pos, arr) => {
   return arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos;
  });
}
// Zero's one-liner works too, here: my shortened version
const Zero_remDups = myArr => myArr.filter(({Time}, i, array) => 
  !array.find((item, j) => +item.Time-Time==0&&i>j));
// also: with "i>j" I pick the first unique (Zero chose the last)


console.log('Cars10m:',Cars10m_remDups(test));
console.log('Akin:',Akin_remDups(test,"Time"));
console.log('Zero:',Zero_remDups(test));
.as-console-wrapper { max-height: 100% !important; top: 0; }