scaryguy
scaryguy

Reputation: 7950

How to insert multiple items to an array at specific indexes inside a multi-dimensional array?

I have an array of arrays.

var arr = [[1,2,3,4,5],[2,3,4,5,6],[3,4,5,6,7],[4,5,6,7,8],[5,6,7,8,9], [6,7,8,9,10], [7,8,9,10,11]];

I want to add a new item in front of and back of multiple items at specific indexes.

What I want to achieve is:

var new_arr = [["x",1,"x",2,3,4,5], [2,3,4,5,"x",6,"x"], [3,4,5,"x",6,"x",7], [4,5,"x",6,"x",7,8], [5,"x",6,"x",7,8,9], ["x",6,"x",7,8,9,10], [7,8,9,10,11]];

The issue is, when I use splice to insert a new item inside the iterated arrays, indexes does change. Because splice is a destructive function.

Here is what I tried:

var result = [];

_.each(arr, function(item, index) {
  index_a = item.indexOf(1);
  index_b = item.indexOf(6);
  var temp_item = item.slice(0);
  if(~index_a || ~index_b) {
    temp_item.splice(index, 0, "x");
    temp_item.splice(index + 2, 0, "x");
      if(index_b > -1) {
        temp_item.splice(index, 0, "x");
      }
  }
  result.push(item);
}

During the iteration above, the first splice works just fine. But the second "x" is not placed properly. I think the reason is first splices' effect on the temp_item array. Because number of items in the array is changing.

So how can I achieve what I want? Thank you.

Upvotes: 0

Views: 2385

Answers (3)

undefined
undefined

Reputation: 2214

I changed a few things, but its working. Oriol is correct the indexOfs you had would always be -1.

In my solution I map over the matrix and evaluate if each row contains 1 or 6, if it does cache the element by index and splice the index with "x",elm"x"

var matrix = [
    [1,2,3,4,5],
    [2,3,4,5,6],
    [3,4,5,6,7],
    [4,5,6,7,8],
    [5,6,7,8,9], 
    [6,7,8,9,10], 
    [7,8,9,10,11]
 ];


function wrapElementWithX(arr, index) {
   // cache the element
   var elm = arr[index];
   // splice with the "x", element, "x"
   arr.splice(index, 1, 'x', elm, 'x');
}


matrix.map(function (row) {   
   var indexOf1 = row.indexOf(1);
   var indexOf6 = row.indexOf(6);
   // if the row has `1`
   // wrap
   if (~indexOf1) {
       wrapElementWithX(row, indexOf1);
   }
   // if the row has `6`
   // wrap
   if (~indexOf6) {
       wrapElementWithX(row, indexOf6);
   }

   return row;
});

also go a jsfiddle example

Upvotes: 1

charlietfl
charlietfl

Reputation: 171669

I think this does what you want. Splicing the higher index first maintains lower index posiitoning

function padArr(val, arr){
    arr.forEach(function(subArr){
        var idx = subArr.indexOf(val);
        if( idx >-1){
           subArr.splice(idx+1,0,'x' );
           subArr.splice(idx,0,'x')
        }       
    });
    return arr;
}

// usage
arr = padArr(1, arr);
arr = padArr(6, arr);

DEMO

Upvotes: 1

chris
chris

Reputation: 1894

Can you just add the second one first? That won't change the index of the first.

Upvotes: 2

Related Questions