将数组元素移动到数组的另一个索引中

时间:2016-06-12 06:06:18

标签: javascript arrays

不确定这是否可能重复,但我在尝试考虑在填充元素数组的数组中移动元素的最佳方法时遇到了一些麻烦。

如:

var foo = [
    [ {obj: 1}, {obj: 2}, {obj: 3}, {obj: 4} ],
    [ {obj: 5}, {obj: 6}, {obj: 7}, {obj: 8} ], 
    [ {obj: 9}, {obj: 10}, {obj: 11}, {obj: 12} ]
];

如果我删除给定arrayIndex的一个元素,它将删除该元素,然后将所有前进元素向下移动到适当的数组。如果我删除obj 3,结果将是:

var arrayIndex = 0;
var objIndex = 2;

var bar = foo[arrayIndex].splice(objIndex, 1);

结果:

bar = [
    [ {obj: 1}, {obj: 2}, {obj: 4}, {obj: 5} ],
    [ {obj: 6}, {obj: 7}, {obj: 8}, {obj: 9} ], 
    [ {obj: 10}, {obj: 11}, {obj: 12} ]
];

另一个例子如图所示删除obj 8:

var arrayIndex = 1;
var objIndex = 3;

var bar = foo[arrayIndex].splice(objIndex, 1);

结果:

bar = [
    [ {obj: 1}, {obj: 2}, {obj: 3}, {obj: 4} ],
    [ {obj: 5}, {obj: 6}, {obj: 7}, {obj: 9} ], 
    [ {obj: 10}, {obj: 11}, {obj: 12} ]
];

对我来说,问题是将所有进行中的元素转移到正确的数组位置。另外,我希望删除空数组。 foo的长度会减少。 foo也会发生变异。

这是我尝试过的jsfiddle:https://jsfiddle.net/mLw8kncn/1/

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:3)

一种简单的方法是将您的项目存储在一维数组而不是二维数组中。然后操纵索引。

var foo = [ {obj: 1}, {obj: 2}, {obj: 3}, {obj: 4},
    {obj: 5}, {obj: 6}, {obj: 7}, {obj: 8},
    {obj: 9}, {obj: 10}, {obj: 11}, {obj: 12} ];

function remove(arrayIndex, objIndex) {
    var realIndex = arrayIndex * 4 + objIndex;
    foo.splice(realIndex, 1);
}

否则,您必须在每次拼接后重新排列项目。

function remove(arrayIndex, objIndex) {
    foo[arrayIndex].splice(objIndex, 1);

    for (var i = arrayIndex + 1; i < foo.length; i++) {
        var obj = foo[i].shift();
        foo[i - 1].push(obj);
    }

    if (foo[foo.length - 1].length <= 0) {
        foo.pop();
    }
}

这很复杂。

答案 1 :(得分:0)

你可以使用一个函数将数组暂时展平为1维(保留子数组原始大小的记录),然后在其上应用标准splice,最后根据该数据重建2D数组。记录的尺寸信息。

这将有益于您可以使用splice的所有功能一次删除多个元素和/或在同一操作中插入其他元素。

因此,给定的索引必须是索引,就像输入数组是1维的一样:

function splice2d(a, start, deleteCount /*, item1, item2, ...*/){
    var flat = [], sizes = [];
    // Make a flat array, keeping record of subarray sizes
    while (a.length) {
        sizes.push(a[0].length);
        flat = flat.concat(a.shift());
    };
    // Apply original splice to flat array
    [].splice.apply(flat, [].slice.call(arguments, 1));
    // Reconstruct 2D array again based on sizes
    while (sizes.length) {
        a.push(flat.splice(0, sizes.shift()));
    }
    return a;
}

// Sample data
var foo = 
    [[{obj: 1}, {obj: 2}, {obj: 3}, {obj: 4}],
    [{obj: 5}, {obj: 6}, {obj: 7}, {obj: 8}], 
    [{obj: 9}, {obj: 10}, {obj: 11}, {obj: 12}]]

// Mutate
splice2d(foo, 2, 1);
// Output result
console.log(foo);

答案 2 :(得分:0)

我猜Array.prototype.reduce()是这项工作的理想选择。你可以这样做

var        foo =  [[{obj: 1}, {obj: 2}, {obj: 3}, {obj: 4}],
                   [{obj: 5}, {obj: 6}, {obj: 7}, {obj: 8}], 
                   [{obj: 9}, {obj: 10}, {obj: 11}, {obj: 12}]
                  ],
removeAndShift = (a,ai,oi) => ai == a.length-1 ? a[ai].splice(oi,1)
                                               : a.reduce((p,c,i,a) => { if (i == ai+1) {
	                                                                    p.splice(oi,1);
	                                                                    p.push(c.shift());
                                                                         }
                                                                         i > ai+1 && p.push(c.shift());
                                                                         return c;
                                                                       });
 removeAndShift(foo,1,3);
 console.log(foo);

请注意,我们没有做任何事情,只是简单地拼出要删除的项目,如果要从中删除项目的数组项目就在最后。