【问题标题】:remove duplicates from a array of objects [duplicate]从对象数组中删除重复项[重复]
【发布时间】:2017-04-10 05:40:08
【问题描述】:

我有一个包含一些键和值的 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] 部分。有什么简单的方法可以进行上述重复数据删除吗?

提前谢谢你

【问题讨论】:

标签: javascript node.js


【解决方案1】:

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

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]);
    }
}

【讨论】:

  • 这很聪明!
  • @Nina 谢谢你的回复。只是这段代码有效。但是,我正在从文件中提供数组。如何对这种方法进行更改?
  • 收到错误data.filter is not a function。我在这里错过了什么?
  • 你可能错过了JSON.parse(data)
  • 是的,很抱歉我添加了它。但标准输出中没有任何内容。看到[ '[' ]@Nina
【解决方案2】:

为什么你用 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);
});

【讨论】:

    【解决方案3】:

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

    检查这个sn-p

    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);

    希望对你有帮助

    【讨论】:

    • 谢谢极客。这有帮助。你能解释一下这段代码是如何工作的吗?我无法理解这条线在做什么:如何使用 reduce 来获取唯一值?
    • 这条线是做什么的? var object = previous.filter(object =&gt; object.timestamp === current.timestamp);return previous;}, [])
    • 过滤已有物品与当前物品时间戳相等的对象
    • 这个操作符是做什么的? =&gt;
    【解决方案4】:

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

     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))

    【讨论】:

    • 非常简单和好的答案。完全明白了。谢谢
    猜你喜欢
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 2022-12-05
    相关资源
    最近更新 更多