Reputation: 805
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.
Upvotes: 3
Views: 497
Reputation: 7591
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
data[0].length
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) );
Upvotes: 1
Reputation: 3400
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.
Upvotes: 1