【问题标题】:remove duplicated array of object using normal for loop使用普通 for 循环删除重复的对象数组
【发布时间】:2016-11-18 16:22:39
【问题描述】:

我知道有一个快捷方式,比如使用 loadash 的 uniq,但我尝试使用原生 for 循环删除重复的对象数组。

var json = [
{name:"james"},
{name:"james_x"},
{name:"jame"},
{name:"james_x"}
]

for(var i = 0;i<json.length-1;i++){
   if(json[i].name == json[i+1].name){
      json.splice(i,i);
   }
}

console.log(json);

https://jsfiddle.net/8wwnvzoc/

我真的很想知道怎么了。

【问题讨论】:

  • 我认为你需要两个 for 循环
  • 将每个名称存储在单独的名称数组中。在每个循环中检查该名称是否已存在于此名称数组中,如果确实将其删除。
  • I REALLY want to know what's wrong. 你遇到错误了吗?结果错误?
  • 您正在将当前项目与列表中的下一个项目进行比较。除非对列表进行排序,否则这是行不通的
  • 使用 for 循环检查排序算法,我建议您删除此问题,因为您将因此获得许多反对票 :)

标签: javascript arrays json loops for-loop


【解决方案1】:

您不应该在迭代数组时修改它。它会导致意想不到的行为。我建议构建一个索引数组以删除,然后在您完全通过数组后删除它们。

要修复您的算法,您需要跟踪所有您看到的名称。您可以为此使用 ES6 集。

var json = [
{name:"james"},
{name:"james_x"},
{name:"jame"},
{name:"james_x"}
]
var indicesToRemove = [];
var seen = new Set();    

for(var i = 0;i<json.length;i++){
   if (seen.has(json[i].name)) {
     indicesToRemove.push(i) 
   } else {
     seen.add(json[i].name);
   } 
}

for(index of indicesToRemove.reverse()) {
    // iterating backwards to prevent indices changing on us...
    json.splice(index,index);
}
console.log(json);

【讨论】:

  • 确实如此,但这仍然不能改变他们的算法一开始就全错的事实。
  • 更新答案以解决多个问题。
  • 如果你想在迭代数组时修改它,迭代 -backwards- 这样索引就不会被弄乱。
【解决方案2】:

尝试在循环之前对数组进行排序,如下所示:

var json = [
{name:"james"},
{name:"james_x"},
{name:"jame"},
{name:"james_x"}
]

json = json.sort(function(a, b){a=a.name;b=b.name;return a<b?-1:a>b?1:0});

for(var i = 0;i<json.length-1;i++){
   if(json[i].name == json[i+1].name){
      json.splice(i,1);
   }
}

console.log(json);

然后,相等的值将彼此接近,因此您的算法将按预期工作...

编辑:

一种可能更好的方法,虽然不使用循环:

var json = [
{name:"james"},
{name:"james_x"},
{name:"jame"},
{name:"james_x"}
]

json = json
    .sort(function(a, b){a=a.name;b=b.name;return a<b?-1:a>b?1:0})
    .reduce(function(a, b){var n=a.length;if(n===0||a[n-1].name!==b.name)a[n]=b;return a},[]);

console.log(json);

【讨论】:

  • 我喜欢你看到这个的方式。这可能是 OP 从一开始就打算让它工作的方式。让我们希望不存在三次重复:P
  • "native for loop",只要求重复。我认为这可能是一个干净简单的解决方案。干得好。
  • @DartFeld triplicates 会杀死这个解决方案吗?
  • @ThianKianPhin 是的,因为您只检查 neihgboor,将其删除,然后递增并转到下一个值。
  • 对于具体提出的问题,这仍然是一个可行的解决方案。
【解决方案3】:

你可以这样做:

var json = [{
   name: "james"
  }, {
  name: "james_x"
  }, {
  name: "jame"
  }, {
  name: "james_x"
  }]

const unique = []

json.forEach(function(item) {
    var existingName = unique.find(function(name) { return name.name === item.name})
    !existingName ? unique.push(item) : null
})

console.log(unique)

【讨论】:

  • 是的,很简单;)它本身很简单,尽管您只想遍历数组中的每个项目,检查该项目是否存在于比较数组中,如果不存在,只需将其推入 :) 我希望这对你有帮助!我应该添加 find 方法是 Array 的原型,它是 ES2015 功能
  • 你在 find() 中传递了name,对吗?请检查。我认为你应该通过item
  • @ThianKianPhin 如果我在其中传递项目,它将不再是比较。item 正在引用您的 JSON 数据。 name 正在引用唯一数组中的项目。如果我要将名称更改为项目,我将检查项目是否等于项目。 item 和 name 可以相互比较,这就是我们在 return 语句中所做的。我希望这是有道理的?
【解决方案4】:

在测试重复时,您没有检查所有其他项目。此外,您在迭代数组时正在修改数组 - 这可能会崩溃。

var json = [
  { name:"james" },
  { name:"james" },
  { name:"james_x" },
  { name:"james_x" },
  { name:"james_x" },
  { name:"jame" },
  { name:"james_x" },
  { name:"jame" },
];

var i = 0,
    index = { /* track what we've seen already */ },
    current;

while (i < json.length) {
  current = json[i].name;

  // check if the name is in index
  if (current in index) {
    // it is, remove it from the array
    json.splice(i, 1);
  } else {
    // not in index, leave it untouched and add it to the index
    // by defining a key in "index" with arbitrary value
    index[current] = true;
    // only step forward when indexing, not when removing
    i++;
  }
}

增量仅限于索引分支,因为如果它也是重复的,算法会意外跳过下一个项目(以下项目将向左/向上移动)。

查看进度(第2列是第1列的以下迭代步骤):

当在两个分支中递增时:

1            1
2            2
3            3
2 <= dupe    2 
2            2 <= accidentally incremented
2            4    missed the previous item
4

正确的增量:

1            1
2            2
3            3
2 <= dupe    2 <= not incremented, all OK
2            2
2            4
4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 2013-09-26
    • 1970-01-01
    • 2020-01-05
    相关资源
    最近更新 更多