2016-06-12 3 views
4

Не уверен, что это может быть дубликат, но я испытываю некоторые проблемы, пытаясь придумать лучший способ переместить элемент в массив, заполненный массивами элементов.Смещение массива элементов в другой индекс массива

Такие, как:

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/

Любая помощь будет оценена.

+0

Если вы удаляете элемент из массива, он автоматически переключается, единственный раз, когда этого не происходит, является фактическое использование delete. Удалить останется за пустым пространством, поэтому длина массива не уменьшится. Если вы используете сращивание, это не должно быть проблемой. – zer00ne

+0

Я просто заметил, что вы хотите переместить элементы в другие массивы, я попытаюсь ответить на эту часть. – zer00ne

+0

Пожалуйста, покажите, что вы делали до сих пор. – 1983

ответ

3

Простым способом является сохранение ваших элементов в массиве 1D вместо 2D. Затем манипулируйте индексами.

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(); 
    } 
} 

И это очень сложно.

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);

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) { 
 
\t                  p.splice(oi,1); 
 
\t                  p.push(c.shift()); 
 
                     } 
 
                     i > ai+1 && p.push(c.shift()); 
 
                     return c; 
 
                     }); 
 
removeAndShift(foo,1,3); 
 
console.log(foo);

Обратите внимание, что мы не делаем ничего, а просто сплайсинга из пункта удалить, если элемент массива, чтобы удалить элемент из находится в самом конце.

+0

Я думаю, вам нужно проверить 'c.length' перед нажатием и сдвигом, иначе вы можете« пустить »на массив. Если OP не хочет этого, конечно: вопрос не уточняется полностью. – 1983

+0

Я бы не сказал, что «сокращение» идеально: вы используете его исключительно для побочных эффектов, а возвращаемое значение не имеет большого смысла. – 1983

+0

@FizzyTea Согласовано с 'c.length', которое может быть проблемой по сокращению. Я должен сказать, что если пара соседних элементов, движущихся вместе как предыдущий и текущий, идеально подходит для этого случая, и я использую эту способность сокращения. ('p.push (c.shift());') Я мог бы изменить код, чтобы вернуть значение точно так, как хотел бы OP, но тогда он был бы гораздо более загадочным. Я думаю, это круто, как есть. – Redu

Смежные вопросы