如何防止向javascript数组添加重复键

iam*_*sar 32 javascript arrays jquery duplicates key-value

我找到了很多相关的问题,并且回答是关于...在循环中并使用hasOwnProperty,但我没有做任何正常工作.我想要做的就是检查数组中是否存在键,如果没有,则添加它.

我从一个空数组开始,然后在用jQuery擦除页面时添加键.

最初,我希望像下面这样简单的东西可以工作:(使用通用名称)

if (!array[key])
   array[key] = value;
Run Code Online (Sandbox Code Playgroud)

不行.跟着它:

for (var in array) {
   if (!array.hasOwnProperty(var))
      array[key] = value;
}
Run Code Online (Sandbox Code Playgroud)

还尝试过:

if (array.hasOwnProperty(key) == false)
   array[key] = value;
Run Code Online (Sandbox Code Playgroud)

这些都没有奏效.要么没有任何东西被推到阵列,要么我尝试的只不过array[key] = value是简单地宣称为什么这么简单如此难以做到.任何使这项工作的想法?

Sam*_*son 38

一般来说,使用对象可以更好地完成,因为JavaScript实际上没有关联数组:

var foo = { bar: 0 };
Run Code Online (Sandbox Code Playgroud)

然后in用来检查密钥:

if ( !( 'bar' in foo ) ) {
    foo['bar'] = 42;
}
Run Code Online (Sandbox Code Playgroud)

正如下面的评论中正确指出的那样,只有当您的键是字符串或可以表示为字符串的项(例如数字)时,此方法才有用.

  • 谢谢乔纳森.光线终于点击了我做错了什么.我正要说你的答案也没有帮助,但经过一些侦探工作后,我很高兴地说它完美无缺.并感谢对象的提示.我会在路上记住这一点. (3认同)
  • ...假设您的值是字符串或可表示为唯一字符串(包括数字). (2认同)

Phr*_*ogz 29

var a = [1,2,3], b = [4,1,5,2];

b.forEach(function(value){
  if (a.indexOf(value)==-1) a.push(value);
});

console.log(a);
// [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

欲了解更多详情,请阅读Array.indexOf.

如果你想依赖jQuery,而是使用jQuery.inArray:

$.each(b,function(value){
  if ($.inArray(value,a)==-1) a.push(value);
});
Run Code Online (Sandbox Code Playgroud)

如果所有的值是简单,唯一可表示为字符串,但是,你应该使用一个对象而不是一个数组,一个潜在的巨大的速度增加(由@JonathanSampson在回答中所述).

  • 此外,使用 `indexOf` 的问题在于它本身会产生一个循环......这使得 [Schlemiel 画家的算法](http://en.wikichip.org/wiki/Schlemiel_the_Painter's_Algorithm) 与添加到数组中的每个项目。 (2认同)

Pav*_*van 20

ES6 中使用 Sets 提供了更好的替代方案。因此,如果您需要一个不应添加重复项的数组,则建议使用 Sets,而不是声明 Arrays。

var array = new Set();
array.add(1);
array.add(2);
array.add(3);

console.log(array);
// Prints: Set(3) {1, 2, 3}

array.add(2); // does not add any new element

console.log(array);
// Still Prints: Set(3) {1, 2, 3}
Run Code Online (Sandbox Code Playgroud)

  • 仅适用于原始类型,因此集合非常有限。 (2认同)
  • @Erik:根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set:Set对象允许您存储任何类型的**唯一值,无论是原始值还是对象参考**。 (2认同)
  • 它接受任何值,但无法评估非基元的相等性。http://jsfiddle.net/poLd7tk6/ (2认同)

Sim*_*ver 6

这是使用传播的简单方法。

此代码将给出重复项:

let colors = ['red', 'orange', 'yellow'];
let moreColors = ['orange', 'green'];

// uh oh! this gives us 'orange' twice
let mergedColors = [...colors, ...moreColors];
Run Code Online (Sandbox Code Playgroud)

因此,您可以在合并数组的同时过滤和删除它们。

let mergedColors = [...colors, ...moreColors.filter(c => !colors.includes(c)) ];
Run Code Online (Sandbox Code Playgroud)