仅当值不存在时才将其压入数组的最有效和干净的方法

Most efficient and clean way to push a value to an array only if it does not exist yet

本文关键字:数组 有效 方法 不存在      更新时间:2023-09-26

假设一个名为myArray的数组包含多个值,但没有重复值。
假设我想只在不会导致重复出现的情况下才将一个值压入其中。我如何确定重复=>通过比较值的id

我想用Lodash#uniq来完成这个任务:

myArray.push(aNewValue);
myArray = _.uniq(myArray,function(item){
   return item.id;
});

然而,我不喜欢对数组重新赋值,特别是在检查之前必须推送的事实…
有没有一种更"实用"的方法来实现它,同时又很短?

我不想为了应用检查而显式地遍历数组。
这就是为什么我尝试使用Lodash

您可以在添加项之前检查项是否存在:

if(myArray.indexOf(aNewValue) == -1) {
    myArray.push(aNewValue);
}

最有效的方法通常是使用一个对象来实现惟一性,因为一个对象最多只能有一个特定值的键。但是,这仅限于字符串和字符串化的东西,因为只有字符串可以是对象键。

这里有两种方法。如果你经常使用数组,那么你应该保持并行结构——一个对象用于惟一性检查,一个数组用于数组性检查。

如果你不经常需要你的数组,也就是说,你想要推送一堆东西,然后有一个数组是唯一的,你可以使用对象,并在你需要的时候把它转换成一个数组(这有点昂贵,所以你只想做一次,但仍然比操作两个不同的结构便宜)。

第一种方法如下:

function Set() {
  this.presence = {};
  this.array = [];
};
Set.prototype.push = function(key, value) {
  if (this.presence[key]) return;
  this.presence[key] = true;
  this.array.push(value);
};
var a = new Set();
a.push(3, { id: 3, value: "SOMETHING" });
a.push(7, { id: 7, value: "SOMETHING ELSE" });
a.push(3, { id: 3, value: "SOMETHING" });
console.log(a.array); // => only 2 elements

第二个,这里:

function Set() {
  this.store = {};
};
Set.prototype.push = function(key, value) {
  this.store[key] = value;
};
Set.prototype.array = function() {
  var that = this;
  return Object.keys(this.store).map(function(key) { return that.store[key]; })
};
...
console.log(a.array()); // note the newly added parentheses :)

这两种方法仍然比使用indexOf在数组中寻找存在更便宜,当你自己进行迭代时更是如此,除非数组非常短。

您可以使用Array.prototype.some()来确定该值是否已经是数组的一部分,例如:

if( myArray.some(function (elem) { return elem.id == newValue.id }) ) 
   myArray.push(newValue);