1

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:

  1. 'GROUP_A' is set
  2. A working array is created and strings 'ONE' and 'TWO' are pushed to 'GROUP_A'.
  3. A 'BREAK' creates a new working array and 'FOUR' is pushed to 'GROUP_A'.
  4. '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.

2
  • 3
    please add your code. what goes wrong? Commented Sep 23, 2021 at 18:37
  • 1
    do you need a number conversion as well? Commented Sep 23, 2021 at 18:43

2 Answers 2

2

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

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

1 Comment

Thanks Nina this was really helpful
0

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

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.