I would be grateful if someone could help me get unstuck. I have an array which I would like to describe using an object. The array looks like this:
const numberGroupArray = [
'GROUP_A',
'ONE',
'TWO',
'BREAK',
'FOUR',
'GROUP_B',
'SIX',
'GROUP_C',
'EIGHT',
'BREAK',
'TEN',
'ELEVEN',
'GROUP_D',
'THIRTEEN',
'BREAK',
'FIFTEEN',
'BREAK',
'SEVENTEEN',
'EIGHTEEN',
'NINETEEN',
]
And the goal object looks like this:
const numberInGroup = {
GROUP_A: [[1, 2], [4]],
GROUP_B: [[6]],
GROUP_C: [[8], [10, 11]],
GROUP_D: [[13], [15], [17, 18, 19]],
};
Where each number refers to an index from the array above. numberInGroup.GROUP_A[0][1]
refers to 'TWO' in the array above. Similarly, numberInGroup.GROUP_D[2][1]
refers to 'SEVENTEEN'.
Attempting to work through the creation of the object:
- 'GROUP_A' is set
- A working array is created and strings 'ONE' and 'TWO' are pushed to 'GROUP_A'.
- A 'BREAK' creates a new working array and 'FOUR' is pushed to 'GROUP_A'.
- 'GROUP_B' is set and steps 2 and 3 repeat for the rest of the initial array.
If you need more info, happy to provide. Thank you in advance.
CodePudding user response:
I would reduce the array by keeping a closure over the last group.
const
data = ['GROUP_A', 'ONE', 'TWO', 'BREAK', 'FOUR', 'GROUP_B', 'SIX', 'GROUP_C', 'EIGHT', 'BREAK', 'TEN', 'ELEVEN', 'GROUP_D', 'THIRTEEN', 'BREAK', 'FIFTEEN', 'BREAK', 'SEVENTEEN', 'EIGHTEEN', 'NINETEEN'],
result = data.reduce((group => (r, v) => {
if (v.startsWith('GROUP_')) {
group = r[v] = [[]];
return r;
}
if (v === 'BREAK') {
group.push([]);
return r;
}
group[group.length - 1].push(v);
return r;
})(), {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
Simply loop over the array and build the result as you go along.
Basically, if you see GROUP_A
(or whatever) then you create a new property in your result, with a blank array. Keep track of the current group and which array you are pushing into.
Then when you hit BREAK
, add a new array and shift the counter.
For values, use your counters and place the value in the right spot.
const numberGroupArray = [
'GROUP_A',
'ONE',
'TWO',
'BREAK',
'FOUR',
'GROUP_B',
'SIX',
'GROUP_C',
'EIGHT',
'BREAK',
'TEN',
'ELEVEN',
'GROUP_D',
'THIRTEEN',
'BREAK',
'FIFTEEN',
'BREAK',
'SEVENTEEN',
'EIGHTEEN',
'NINETEEN',
];
let numberInGroup = {}, // The result object
currGroup, // Which group/property are we inside?
currIdx, // Which sub-array are we pushing to?
isGroup; // Do we need to change to a new group?
numberGroupArray.forEach(val => {
// Is this a new group?
// If so, then make a new property and reset the counters
if ((isGroup = val.match(/GROUP_[A-Z]/))) {
currGroup = isGroup[0];
currIdx = 0;
numberInGroup[currGroup] = [[]];
}
// BREAK means to push a new array into the current group
else if (val === 'BREAK') {
currIdx ;
numberInGroup[currGroup].push([]);
}
// Otherwise push the value into the right spot in the final result
else {
numberInGroup[currGroup][currIdx].push(val);
}
});
console.log(numberInGroup);