3

I'm looping over the following array of arrays and for the first item in the array, I need to insert an object after every item, except the first and maybe last item. The data looks like this...

const data = [
  ['Path', 'Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Score'],
  ['/path-one', 1, 3, 2, 2, 4,  3],
  ['/path-two', 4, 5, 5, 5, 6, 3],
  ['/path-three', 5, 5, 3, 5, 3, 3],
  ['/path-four', 2, 3, 4, 2, 2, 3],
]

For the first row, except the first item and last item, after every other item I want to insert an object {role: 'annotation'}. For the rest of the rows, for every index in the first item array that has the role object, I want to duplicate the previous value such that if the first array after modification is: ['Path', 'Item1', {role: 'annotation'}, 'Item2', {role: 'annotation'}, 'Score'], then the other arrays will follow the pattern ['/path-one', 'value1', 'value1', 'value2', 'value2', 'value3']

My solution so far has been inadequate. Here's what I came up with...

let indexes = []
let scoreIndex
const result = data.map((item, index) => {
  let clone = [...item]
  item.map((i, ix) => {
    if (index === 0) {
      if (ix !== 0 && typeof clone[ix + 1] === 'string' && typeof clone[ix] !== 'object') {
        if (clone[ix + 1] === 'Score') {
          scoreIndex = ix
        }
        indexes.push(ix)
        clone.splice((ix + 1), 0, {role: 'annotation'})
      }
      return i
    } else {
      if (indexes.includes(ix) && ix !== scoreIndex) {
        item.splice((ix + 1), 0, i)
        return i
      }
      return i
    }
  })
  return clone
})

Your help would be greatly appreciated.

2 Answers 2

1

Perhaps I misunderstood something. I assumed the following:

:: The lengths of each array in the data array are the same.

:: You need to inject after each position, which will mess up a for loop that increase it's i(teration) variable.

:: There is always a Path and a Score in the first array.

:: You want to add a new value after each value, apart from the two above.

Solution

  1. Get the length of each array: data[0].length
  2. Loop from the end.
  3. Ignore last position.
  4. Ignore the first position
  5. Splice different value based on if it's the first item in the data array.

I loop over each value once, but I do it in the order of: 'Item5', 4, 6, 3, 3, 'Item4', 2, 5, 5, 2, 'Item3', ...

const data = [
  ['Path', 'Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Score'],
  ['/path-one', 1, 3, 2, 2, 4,  3],
  ['/path-two', 4, 5, 5, 5, 6, 3],
  ['/path-three', 5, 5, 3, 5, 3, 3],
  ['/path-four', 2, 3, 4, 2, 2, 3],
]

function mapArray(data) {
  let secondToLastItem = data[0].length - 2; // 1 & 3
  let FIRST_ITEM = 0; // 4

  for (let index = secondToLastItem; index > FIRST_ITEM; index--) { // 2
    for (let item = 0; item < data.length; item++) {
      let injectedValue = (item == FIRST_ITEM)  // 5
          ? {'role': 'annotation'}
          : data[item][index]; 
      
      data[item].splice(index + 1, 0, injectedValue);
    }
  }
  
  return data;
}

console.log( mapArray(data) );

Sign up to request clarification or add additional context in comments.

Comments

1

This answer is not perfect, but should give an idea on how this can solved.

  const data = [
  ['Path', 'Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Score'],
  ['/path-one', 1, 3, 2, 2, 4,  3],
  ['/path-two', 4, 5, 5, 5, 6, 3],
  ['/path-three', 5, 5, 3, 5, 3, 3],
  ['/path-four', 2, 3, 4, 2, 2, 3],
]
  let indexes = []
let scoreIndex

// This method takes in an error and perform splice with the value passed, if no value passed, it will use the current index value.
const splicer = (arr, index, value) => {
  var length = (arr.length - 1) * 2;
  for(let i = 1; i < length; i = i+2) {
    if(value) {
      arr.splice(i, 0, value);
    } else {
      arr.splice(i, 0, arr[i]);
    }
  }
  return arr;
}

// This method goes through data (array of arrays) and call splicer
const output = data.map((item, index) => {
  if(index == 0) {
    splicer(item, 0, {role : "annotation"})
  } else {
    splicer(item, 0);
  }
});

Output

["Path",{"role":"annotation"},"Item1",{"role":"annotation"},"Item2",{"role":"annotation"},"Item3",{"role":"annotation"},"Item4",{"role":"annotation"},"Item5",{"role":"annotation"},"Score"]
["/path-one",1,1,3,3,2,2,2,2,4,4,3,3]
["/path-two",4,4,5,5,5,5,5,5,6,6,3,3]
["/path-three",5,5,5,5,3,3,5,5,3,3,3,3]
["/path-four",2,2,3,3,4,4,2,2,2,2,3,3]

With map, it is a little tough to skip values (it should be possible), so have used a plan for loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.