Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript:数组排序优化_Javascript_Arrays_Sorting - Fatal编程技术网

JavaScript:数组排序优化

JavaScript:数组排序优化,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有一个带有嵌套对象的JavaScript数组,例如:[{id:1,position:1},{id:2,position:2},{id:3,position:3},{id:4,position:4},{id:7,position:7},{id:5,position:5},{id:6,position 6}]。这只是一个例子,实际上我的应用程序中有一个数组,有100条记录。我试图用JavaScript数组排序方法对数组进行排序。假设数组名为myArray,那么我将执行以下操作: myArray.s

我有一个带有嵌套对象的JavaScript数组,例如:
[{id:1,position:1},{id:2,position:2},{id:3,position:3},{id:4,position:4},{id:7,position:7},{id:5,position:5},{id:6,position 6}]
。这只是一个例子,实际上我的应用程序中有一个数组,有100条记录。我试图用JavaScript数组排序方法对数组进行排序。假设数组名为myArray,那么我将执行以下操作:

myArray.sort(function(a, b) {
   return a.position- b.position;
});

它工作正常,但冻结了我的浏览器。有没有什么好的优化方法来进行排序。

您可以自己实现像快速排序和合并排序这样非常高效的排序算法


您可以找到javascript sort()和MergeSort实现之间的比较。我建议你多读一些,找到一个更适合你的问题

在您稍后的一条评论中,您提到数据是一点一点地来的,而不是一次全部来的。但是
Array.prototype.sort()
每次都必须对整个数组进行返工,即使它大部分已经排序;只有少数元素超出了它们应该位于的位置

对于像您这样的情况,我倾向于使用插入排序,而不是JavaScript的内置排序方法(通常是合并排序或快速排序的变体,具体取决于引擎)插入排序作为通用排序算法不是很好,但当您只需要向已排序的数组中添加两个项目时,插入排序就很好了。这就是您在这里要做的,所以听起来很适合

下面是该算法的基本实现

/**
 * Compare two items as though they were strings.
 *
 * This is like the default comparison for Array.prototype.sort()
 *
 * @param {*} a The first item
 * @param {*} b The second item
 *
 * @return -1 if a is less, 1 is b is less, 0 otherwise
 */
function compareStrings(a, b) {
    var sa = String(a),
        sb = String(b);

    if (sa < sb) {
        return -1;
    }
    if (sa > sb) {
        return 1;
    }
    return 0;
}

/**
 * Insert a new item into a sorted array.
 *
 * The compareFunction callback function works as for the analogous argument
 * in Array.prototype.sort(). Leave unspecified to compare lexically.
 *
 * @param {Array}     data            A sorted array, into which to put this item
 * @param {*}         newItem         The item to add to the data.
 * @param {Function=} compareFunction Optional comparison function.
 */
function arrayInsert(data, newItem, compareFunction) {
    var stop = data.length,
        i = 0;

    compareFunction = compareFunction || compareStrings;
    while (i < stop) {
        if (compareFunction(newItem, data[i]) < 0) {
            data.splice(i, 0, newItem);
            return;
        }
        i += 1;
    }
    // If we got this far, then this should be the last item.
    data.push(newItem);
}
/**
*将两个项目作为字符串进行比较。
*
*这类似于Array.prototype.sort()的默认比较
*
*@param{*}a是第一项
*@param{*}b第二项
*
*@return-1如果a小于,则1表示b小于,否则为0
*/
功能比较(a、b){
var sa=字符串(a),
sb=字符串(b);
if(sasb){
返回1;
}
返回0;
}
/**
*将新项插入已排序的数组中。
*
*compareFunction回调函数的作用与类似参数相同
*在Array.prototype.sort()中。保留未指定项以便在词汇上进行比较。
*
*@param{Array}data排序后的数组,将此项放入其中
*@param{*}newItem要添加到数据中的项。
*@param{Function=}compareFunction可选的比较函数。
*/
函数arrayInsert(数据、新项、比较函数){
var stop=data.length,
i=0;
compareFunction=compareFunction | | compareStrings;
当(我<停止){
if(compareFunction(newItem,data[i])<0){
数据拼接(i,0,新项);
返回;
}
i+=1;
}
//如果我们走到这一步,那么这应该是最后一项了。
数据推送(newItem);
}
当页面加载时,整个数组仍然需要排序一次,您不应该使用插入排序(最好让服务器向您发送已排序的数据,但如果您不能这样做,则使用普通的
array.prototype.sort
函数)。然后,当您获得新数据时,为您获得的每个新数据项调用一次
arrayInsert(data,newItem,/*您的比较函数*/)
。这应该会加快速度


如果这仍然太慢,那么您可以将新数据项放入队列,并在页面中添加一个短计时器。此计时器每隔几毫秒检查一次队列,如果有任何项目等待,它会将其中一个项目添加到数组中。这实际上不会使事情变得更快(事实上,它会使事情变得更慢),但页面不应该再冻结。

我建议使用二进制搜索来定义插入新对象的索引,而不是先推后排序

以下代码没有开销,因为没有函数调用

还有一个变量
iteration
,它只能作为见证,您可以将其丢弃

我对以下代码进行了分析

假设您的
a
已排序并且包含唯一的位置,则可以执行此操作

// THIS SECTION IS ONLY THERE TO SUIT YOUR CONSTRAINTS (100 objects in a)
var a = [];

for (var i = 0; i < 200; i++) {
    if (i & 1) {
        a.push({ id: i, position: i }); // objects are pushed only if they position is odd
    }
}

// this means o.position (our new object) can have any even value, we know that it won't already exist in a
var o = {
    id: 2,
    position: 2
};
var start = 0,
    end = (a.length - 1),
    mid = end >>> 1,
    left,
    right;

var iterations = 0;

while (mid !== a.length - 1) {
    if (mid > 0) {
        leftIsMore = a[mid - 1].position > o.position;
    } else {
        leftIsMore = false;
    }

    rightIsLess = a[mid].position < o.position;

    if (!leftIsMore && !rightIsLess) {
        break;
    } else if (leftIsMore) {
        end = mid - 1;
    } else {
        start = mid + 1;
    }

    mid = (start + end) >>> 1;
    iterations++;
}

var index = mid;

if (index === a.length - 1) {
    a.push(o);
} else {
    a.splice(index, 0, o);
}

console.log(a, 'Number of iterations to insert: ', iterations);
//此部分仅用于满足您的约束(一个区域中有100个对象)
var a=[];
对于(变量i=0;i<200;i++){
如果(i&1){
a、 push({id:i,position:i});//仅当对象的位置为奇数时才推送它们
}
}
//这意味着o.position(我们的新对象)可以有任何偶数值,我们知道它不会已经存在于
变量o={
id:2,
职位:2
};
var start=0,
结束=(a.长度-1),
mid=结束>>>1,
左边
正确的;
var迭代次数=0;
while(mid!==a.length-1){
如果(中间>0){
leftIsMore=a[mid-1]。位置>o位置;
}否则{
leftIsMore=false;
}
无右=a[中间]。位置>>1;
迭代++;
}
var指数=mid;
如果(索引===a.length-1){
a、 推(o);
}否则{
a、 拼接(指数0,o);
}
log(a,‘要插入的迭代次数:’,迭代次数);

如果冻结只是因为您没有使用
排序
方法,请尝试以下操作:

myArray.sort(function(a, b) {
    return a.position- b.position > 0 ? 1 : -1;
});

每个浏览器都会出现这种情况吗?您是如何确定这是导致冻结的原因的?如果它正在工作,但冻结了浏览器,您必须使用
setTimeout()
部分设置它(由于单线程)。这些数据是否来自某种请求?如果是这样,在传输数据之前让服务器对数据进行排序可能会更好。尝试将其添加到
setTimeout(sortFunction(){…},0)
。要预测新位置,我还需要循环现有位置