如何保持Javascript数组排序,而不进行排序

时间:2013-12-03 13:01:54

标签: javascript arrays node.js sorting

我有一个Node.js应用程序,我必须经常做以下事情: - 检查特定阵列是否已包含某些元素 - 如果元素确实存在,请更新它 - 如果元素不存在,则将其推送到数组,然后使用下划线_.sortBy

对其进行排序

为了检查元素中是否已经存在元素,我使用这个二进制搜索函数: http://oli.me.uk/2013/06/08/searching-javascript-arrays-with-a-binary-search/

这样,当数组的大小增加时,排序变得越来越慢。 我假设数组大小可能会增加到每个用户最多20 000个项目。最终会有成千上万的用户。数组按键排序,这是一个很短的字符串。如果需要,它可以转换为整数。

所以,我需要一种更好的方法来保持数组排序, 每当新元素被推到它上时,而不是对它进行排序。

所以,我的问题是,我应该如何/可以编辑我使用的二进制搜索算法,以使我能够 获取应放置新元素的数组索引(如果数组中尚不存在)? 或者有什么其他可能性来实现这一目标。当然,我可以使用某种从头开始并经过数组的循环,直到它找到新元素的位置。

所有数据都存储在MongoDB中。

换句话说,我想保持数组排序,而不是每次推送新元素时都对它进行排序。

3 个答案:

答案 0 :(得分:7)

当找不到匹配项时,很容易修改此binaryIndexOf函数以返回下一个元素的索引:

function binaryFind(searchElement) {
  'use strict';

  var minIndex = 0;
  var maxIndex = this.length - 1;
  var currentIndex;
  var currentElement;

  while (minIndex <= maxIndex) {
    currentIndex = (minIndex + maxIndex) / 2 | 0;
    currentElement = this[currentIndex];

    if (currentElement < searchElement) {
      minIndex = currentIndex + 1;
    }
    else if (currentElement > searchElement) {
      maxIndex = currentIndex - 1;
    }
    else {
      return { // Modification
        found: true,
        index: currentIndex
      };
    }
  }      

  return { // Modification
    found: false,
    index: currentElement < searchElement ? currentIndex + 1 : currentIndex
  };
}

所以,现在它返回像:

这样的对象
{found: false, index: 4}

其中index是找到的元素或下一个元素的索引。

因此,现在插入一个新元素将如下所示:

var res = binaryFind.call(arr, element);
if (!res.found) arr.splice(res.index, 0, element);

现在您可以将binaryFind添加到Array.prototype以及添加新元素的帮助:

Array.prototype.binaryFind = binaryFind;

Array.prototype.addSorted = function(element) {
  var res = this.binaryFind(element);
  if (!res.found) this.splice(res.index, 0, element);
}

答案 1 :(得分:2)

如果您的数组已经排序并且您想插入一个元素,为了保持它的排序,您需要将它插入数组中的特定位置。幸运的是,数组有一个方法可以做到这一点: Array.prototype.splice

所以,一旦你得到你需要插入的索引(你应该通过对二进制搜索的简单修改),你可以这样做:

myArr.splice(myIndex,0,myObj);
// myArr your sorted array
// myIndex the index of the first item larger than the one you want to insert
// myObj the item you want to insert

编辑:您的二进制搜索代码的作者有相同的想法:

  

所以,如果你想插入一个值,并想知道你应该在哪里   把它,你可以运行该函数并使用返回的数字   将值拼接到数组中。   Source

答案 2 :(得分:0)

我知道这是一个旧问题的答案,但使用javascripts array.splice()以下内容非常简单。

function inOrder(arr, item) {
    /* Insert item into arr keeping low to high order */

    let ix = 0;
    while (ix < arr.length) {
        //console.log('ix',ix);
        if (item < arr[ix]) { break; }
        ix++;
    }

    //console.log('  insert:', item, 'at:',ix);
    arr.splice(ix,0,item);
    return arr
}

通过反转测试可以将顺序更改为从高到低