从对象数组中删除重复项

时间:2016-11-25 19:42:26

标签: javascript node.js

我有一些带有一些键和值的javascript对象。下面是我的数组的样子。

[
{
"timestamp": 1474328370007,
"message": "hello"
},
{
"timestamp": 1474328302520,
"message": "how are you"
},
{
"timestamp": 1474328370007,
"message": "hello"
},
{
"timestamp": 1474328370007,
"message": "hello"
}
]

我想删除对象中时间戳的重复发生,并且只保留该对象的单个发生。匹配应该基于时间戳而不是消息发生。

预期产出

[
{
 "timestamp": 1474328302520,
"message": "how are you"
},
{
"timestamp": 1474328370007,
"message": "hello"
}
]

尝试这样的事情

var fs = require('fs');

fs.readFile("file.json", 'utf8', function (err,data) {
if (err) console.log(err);;
console.log(data);
// var result = [];
for (i=0; i<data.length;i++) {
  if(data[i].timestamp != data[i+1].timestamp)
    console.log('yes');
  }
});

数组结束后我无法找出data[i+1]部分。有没有简单的方法可以进行上述重复数据删除?

提前谢谢

4 个答案:

答案 0 :(得分:5)

您可以将对象用作哈希表并检查。

var array = [{ "timestamp": 1474328370007, "message": "hello" }, { "timestamp": 1474328302520, "message": "how are you" }, { "timestamp": 1474328370007, "message": "hello" }, { "timestamp": 1474328370007, "message": "hello" }],
    result = array.filter(function (a) {
        return !this[a.timestamp] && (this[a.timestamp] = true);
    }, Object.create(null));

console.log(result);

您可以使用散列的变量和过滤结果的变量,例如

var hash = Object.create(null),
    result = [];

for (i = 0; i < data.length; i++) {
    if (!hash[data[i].timestamp]) {
        hash[data[i].timestamp] = true;
        result.push(data[i]);
    }
}

答案 1 :(得分:3)

为什么你用fs.readFile读取json文件?只需要它。

过滤作业本身:

const arr = require('./file.json')

const tester = []
const result = []

arr.forEach(function(el) {
  if (tester.indexOf(el.timestamp) === -1) {
    tester.push(el.timestamp)
    result.push(el)
  }
})

<强>更新 优雅的解决方案使用 Array.prototype.reduce

const result = arr.reduce(function(result, current) {
  if (result.indexOf(current) === -1) result.push(current);
}, []);

<强>更新 大多数情况下效率最高:

const hashmap = {};
arr.forEach(el => {
  if(!hash[el.timestamp]) hash[el.timestamp] = el;
})
const result = Object.values(hashmap);

<强>更新 对所有情况最有效和稳定。散列函数会在每种情况下引起碰撞的情况下,上层解决方案将非常低效。这个将是最稳定的一个:

const result = [];
arr.sort((a,b) => a.timestamp - b.timestamp);
arr.forEach(el => {
  const last = result[result.length-1];
  if (el.timestamp === last.timestamp) continue;
  result.push(el);
});

答案 2 :(得分:1)

一种简单的方法是使用一组标志。肯定有更好的方法,但这是一个相当简单的方法,它应该适合你。

 data = [
        {
            "timestamp": 1474328370007,
            "message": "hello"
        },
        {
            "timestamp": 1474328302520,
            "message": "how are you"
        },
        {
           "timestamp": 1474328370007,
           "message": "hello"
        },
        {
           "timestamp": 1474328370007,
           "message": "hello"
        }
    ];

    // array to store result
    result = [];
    // store flags
    flags = [];

    for (i=0; i<data.length;i++) {
        // dont run the rest of the loop if we already have this timestamp
        if (flags[data[i].timestamp]) continue;

        // if we didn't have the flag stored, then we need to record it in the result
        result.push(data[i]);

        // if we don't yet have the flag, then store it so we skip it next time
         flags[data[i].timestamp] = true;
    }

    // stringify the result so that we can display it in an alert message
    alert(JSON.stringify(result))

答案 3 :(得分:0)

您可以使用reduce并获取唯一项

检查此代码段

var arr = [{
  "timestamp": 1474328370007,
  "message": "hello"
}, {
  "timestamp": 1474328302520,
  "message": "how are you"
}, {
  "timestamp": 1474328370007,
  "message": "hello"
}, {
  "timestamp": 1474328370007,
  "message": "hello"
}];

var elements = arr.reduce(function(previous, current) {

  var object = previous.filter(object => object.timestamp === current.timestamp);
  if (object.length == 0) {
    previous.push(current);
  }
  return previous;
}, []);

console.log(elements);

希望有所帮助