只有在Javascript中不存在数组元素时才附加数组元素

时间:2011-10-03 18:08:54

标签: javascript arrays sorting set

我需要在数组中添加一个元素,只要它在Javascript中不存在。基本上我将数组视为一组。

我需要将数据存储在数组中,否则我只使用一个可以用作集合的对象。

我写了下面的数组原型,想听听是否有人知道更好的方法。这是一个O(n)插入。我希望做O(ln(n))插入,但是,我没有看到 easy 方法将元素插入到排序数组中。对于我的应用程序,数组长度将非常小,但我仍然更喜欢符合公认规则以获得良好算法效率的东西:

Array.prototype.push_if_not_duplicate = function(new_element){
    for( var i=0; i<this.length; i++ ){
        // Don't add if element is already found
        if( this[i] == new_element ){
            return this.length;
        }
    }
    // add new element
    return this.push(new_element);
}

4 个答案:

答案 0 :(得分:4)

如果我理解正确,你已经有一个排序数组(如果你没有排序数组,那么你可以使用Array.sort方法对数据进行排序),现在你想要添加一个元素,如果它不是已存在于数组中。我在google closure library中提取了二进制插入(使用二进制搜索)方法。相关代码本身看起来像这样,它是O(log n)操作,因为二进制搜索是O(log n)。

function binaryInsert(array, value) {
  var index = binarySearch(array, value);
  if (index < 0) {
    array.splice(-(index + 1), 0, value);
    return true;
  }
  return false;
};

function binarySearch(arr, value) {
  var left = 0;  // inclusive
  var right = arr.length;  // exclusive
  var found;
  while (left < right) {
    var middle = (left + right) >> 1;

    var compareResult = value > arr[middle] ? 1 : value < arr[middle] ? -1 : 0;
    if (compareResult > 0) {
      left = middle + 1;
    } else {
      right = middle;
      // We are looking for the lowest index so we can't return immediately.
      found = !compareResult;
    }
  }
  // left is the index if found, or the insertion point otherwise.
  // ~left is a shorthand for -left - 1.
  return found ? left : ~left;
};

用法是binaryInsert(数组,值)。这也保持了数组的种类。

答案 1 :(得分:1)

我之前创建了一个(简单和不完整)Set类型:

var Set = function (hashCodeGenerator) {
    this.hashCode = hashCodeGenerator;
    this.set = {};
    this.elements = [];
};
Set.prototype = {
  add: function (element) {
    var hashCode = this.hashCode(element);
    if (this.set[hashCode]) return false;
    this.set[hashCode] = true;
    this.elements.push(element);
    return true;
  },
  get: function (element) {
    var hashCode = this.hashCode(element);
    return this.set[hashCode];
  },
  getElements: function () { return this.elements; }
};

您只需要为对象找到一个好的hashCodeGenerator函数。如果您的对象是基元,则此函数可以返回对象本身。然后,您可以从getElements访问器访问数组形式的set元素。插入是O(1)。空间要求是O(2n)。

答案 2 :(得分:1)

删除了我的另一个答案,因为我错过了数组已排序的事实。

您编写的算法遍历数组中的每个元素,如果没有匹配,则在末尾添加新元素。我认为这意味着你之后正在运行另一种类型。

使用分而治之算法可以改善整个算法。选择数组中间的元素,与新元素进行比较并继续,直到找到要插入的位置。它会比你的上述算法略快,并且之后不需要排序。

如果您需要帮助制定算法,请随时提出。

答案 3 :(得分:0)

如果您的数组是二叉树,则可以通过将新元素放在末尾并将其冒泡到位来插入O(log n)。检查重复项也需要执行O(log n)。

Wikipedia has a great explanation.