JavaScript中重新排序数组

4

有许多关于这个主题的问题/答案。但没有一个符合我的具体情况。希望有人能帮忙:

我有一个类似以下的索引数组:

var indexes = [24, 48, 32, 7, 11];

还有一个类似于这样的对象数组:

var items = [{
              name : "whatever",
              selected : false,
              loading : true,
              progress : 55,
              complete : false
},
{
              name : "whatever 2",
              selected : false,
              loading : false,
              progress : 100,
              complete : true
}];

indexes 数组中的每个整数都对应于 items 数组中一个对象的实际索引。

最后,我有一个变量用于定义 items 数组中新插入位置:

 var insertindex = ??

我想要做的是将“items”数组中所有索引存储在“indexes”数组中的“objects”取出并删除它们,最后将它们全部放在变量“insertindex”定义的特定索引旁边,再放回原位置。
我一直试图使用“splice()”方法,通过将每个索引处的对象复制到一个临时数组中,然后从原始数组中删除它们,最后循环遍历这个新的临时数组,并将它们放回到原始“items”数组中的新位置。但是我似乎陷入了困境,无法使其正确运作。
简而言之,我只想从“items”数组中取出所有与索引数组中定义的索引匹配的对象,将它们聚合并重新插入到预定义的索引中,放回“items”数组中。
为了帮助进行概念上的可视化,如果您将应用程序想象成一个JavaScript文件管理器,允许重新排序不必相邻的多个文件选择。 索引数组定义当前选择,“items”数组定义文件列表。 最后,“rearoderindex”定义了所有选定文件应该移动到的新插入位置。
编辑:正如这里所建议的那样,这是我目前正在尝试的代码:
function reorder(items, indexes, insertindex){

        var offset = 0;
        var itemscopy = items.slice(0); //make shallow copy of original array
        var temparray = new Array(); // create temporary array to hold pulled out objects

        //loop through selected indexes and copy each into temp array
        for(var i=0, len=indexes.length; i<len; i++){ 
            array[i] = itemscopy[self.cache.selecteditems[i]];
        }


        //remove all selected items from items array
        for(var i=0, len=indexes.length; i<len; i++){
            items.splice(indexes[i], 1);
        }

        //finally loop through new temp array and insert the items back into the items array at the specified index, increasing the index each iteration using the offset variable.
        for(var i=0, len=temparray.length; i<len; i++){
            items.splice((insertindex+offset), 0, array[i]);
            offset++;
        }

}

我知道这很糟糕,而且循环三次不应该是必要的。但是我一直在尝试许多不同的方法,有些方法在一个方向上重新排序时有效,有些在另一个方向上有效,大多数情况下则根本无效。我想等到函数能够准确地运行后再优化它。

我确定我一定做了极其愚蠢或完全忽略了某些事情,但就目前而言,我无法弄清楚是什么。


4
请发出您拥有的剪接代码,或者更好的办法是制作一个JSFiddle。这听起来对我来说是正确的轨迹。 - Matt Dodge
2个回答

5
如果您不关心indexes数组的顺序,我建议采用另一种简短的解决方案:
items.splice.apply(items, [insertIndex, 0].concat(indexes.sort(function(a, b) {
    return a - b;
})).map(function(i, p) {
    return p > 1 ? items.splice(i - p + 2, 1).pop() : i;
}));

演示: http://jsfiddle.net/T83fB/

简而言之,我使用了Array.map()方法,但是它不支持旧版IE浏览器。不过,我们可以从MDN中轻松地使用一个shim。


这太好了,是一个非常优雅的解决方案!谢谢VisioN。我稍后会进行彻底测试,并在答案中重新授予你,如果它被证明是最好的解决方案:) 多谢! - gordyr

2
您可以使用.splice()函数向数组添加元素,也可以从中删除元素。基本原则是:
  1. 将索引按升序排列
  2. 遍历indexes,在该索引处删除元素(调整已删除项数),并将其存储在removedItems数组中
  3. removedItems数组重新添加到所需的索引中
执行此操作的代码如下所示:
var removedItems = [];
// sort indexes
indexes.sort(function(a, b) {
    if(a < b) return -1;
    else if(b < a) return 1;
    return 0;
});
for(var i = 0; i < indexes.length; i++) {
    var index = indexes[i];
    removedItems.push(items.splice(index - removedItems.length, 1));
}
var insertIndex = 1;
items.splice.apply(items, [insertIndex, 0].concat(removedItems));

请看这个 jsFiddle 演示


这个完美无缺! :) 太棒了。系统也提供了一个答案,在最小测试下似乎也能工作。在我选择采纳答案之前,您能否评论哪个方案是最好/性能最佳的呢?不管怎样,非常感谢您。那真的帮了大忙。 - gordyr
1
@gordyr 这是否意味着您不关心 indexes 数组元素的顺序? - VisioN
@VisioN 在这种情况下,不需要。由于项目(文件)按照索引递增的顺序从左到右,从上到下显示,将它们按升序排序是我的用例的正确行为。值得注意的是,除了Anthony的答案之外,我还必须测试所选code索引值中有多少小于'code'插入索引,并通过该数量偏移插入位置。这意味着我可以重新排序由数组开头和结尾的项目组成的文件选择,插入到中间某个位置。 - gordyr
如果是这样,我已经添加了我的版本,它更短,并且不使用额外的资源。 - VisioN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接