Home > Enterprise >  Group objects with keys based on its index to a new array
Group objects with keys based on its index to a new array

Time:05-06

Does anyone know how to group object of arrays to a new array of object arrays based on its index with Javascript? I'm quite new to this so I'm quite stuck here

For example I have this object :

{
  'first': [
    {
      name: 'jimmy',
      text: 'I love you'
    },
    {
      name: 'jimmy',
      text: 'I miss you!'
    },
    {
      name: 'jimmy',
      text: 'I hate you!'
    }
  ],
  'second': [
    {
      name: 'jeremy',
      text: 'Wow'
    }
  ],
  'third': [
    {
      name: 'john',
      text: 'You ugly'
    },
    {
      name: 'john',
      text: 'You handsome'
    },
    {
      name: 'john',
      text: 'you beautiful'
    }
  ],
 'fourth': [
    {
      name: 'tom',
      text: 'this is cool!'
    },
    {
      name: 'tom',
      text: 'this is hard'
    }
  ]
}

which I want to transform to something like :

[
  [
    {
      name: 'jimmy',
      text: 'I love you'
    },
    {
      name: 'jeremy',
      text: 'Wow'
    },
    {
      name: 'john',
      text: 'You ugly'
    },
    {
      name: 'tom',
      text: 'this is cool!'
    },
  ],
  [
    {
      name: 'jimmy',
      text: 'I miss you!'
    },
    {
      name: 'john',
      text: 'You handsome'
    },
    {
      name: 'tom',
      text: 'this is hard'
    }
  ],
  [
    {
      name: 'jimmy',
      text: 'I hate you!'
    },
    {
      name: 'john',
      text: 'you beautiful'
    }
  ]
]

so 'first'[1],'second'[1], 'third'[1], 'fourth'[1] should group to the first array as array of objects and 'first'[2],'second'[2], 'third'[2], 'fourth'[2] should go to the second array as array of objects and so on..

CodePudding user response:

Mushroomator's answer is probably the most concise way to do this.

If you're newer to JavaScript, functional programming, or programming altogether, I think the following is a decent intro-level approach that might be easier to understand.

The underlying logic is the same, the steps have just been made more explicit/more apparent.

  1. Create an output array that will hold the result.
  2. Get the first, second, third, and fourth arrays from data by using Object.values().
  3. For each of the arrays from step 2, iterate over their items using a for loop.
  4. If output doesn't already have a nested array for the current index, create one.
  5. Array#push() the item in the current array at the current index into the array at the current index in the output.

const data = {
  first:[{name:"jimmy",text:"I love you"},{name:"jimmy",text:"I miss you!"},{name:"jimmy",text:"I hate you!"}],
  second:[{name:"jeremy",text:"Wow"}],
  third:[{name:"john",text:"You ugly"},{name:"john",text:"You handsome"},{name:"john",text:"you beautiful"}],
  fourth:[{name:"tom",text:"this is cool!"},{name:"tom",text:"this is hard"}]
};

const output = [];
for (let arr of Object.values(data)) {
  for (let i = 0; i < arr.length; i  ) {
    if (output[i] === undefined) {
      output[i] = [];
    }
    output[i].push(arr[i]);
  }
}

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

You can use reduce() in order to do this.

const input = {
  first: [
    {
      name: "jimmy",
      text: "I love you",
    },
    {
      name: "jimmy",
      text: "I miss you!",
    },
    {
      name: "jimmy",
      text: "I hate you!",
    },
  ],
  second: [
    {
      name: "jeremy",
      text: "Wow",
    },
  ],
  third: [
    {
      name: "john",
      text: "You ugly",
    },
    {
      name: "john",
      text: "You handsome",
    },
    {
      name: "john",
      text: "you beautiful",
    },
  ],
  fourth: [
    {
      name: "tom",
      text: "this is cool!",
    },
    {
      name: "tom",
      text: "this is hard",
    },
  ],
};

const output = Object.values(input).reduce(
  (all, cur) => (
    cur.forEach((item, idx) =>
      idx < all.length ? all[idx].push(item) : (all[idx] = [item])
    ),
    all
  ),
  []
);
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

First of all, we don't care about the keys of the input Object, therefore we can use Object.values() to just obtain the values.

Then, the idea is to start with an empty array all (second argument of reduce()) and then loop over the input.

Then for each element cur we loop over all the items of this element and for each of these items we check whether we have this element's index (idx) in the all array already.

If we don't, this index is larger then any of the previously added indices and we need to extend our all array in order to hold that values. As we expect multiple values for a given spot, we need to use an array as an value for that spot. If we already have at least one value for a given index, we already have an array at the given index and we just need to push() the new item onto the all array.

CodePudding user response:

Here is an approach where you shift from each subarray the next item so to collect the next subarray for the result:

let obj = {'first': [{name: 'jimmy',text: 'I love you'},{name: 'jimmy',text: 'I miss you!'},{name: 'jimmy',text: 'I hate you!'}],'second': [{name: 'jeremy',text: 'Wow'}],'third': [{name: 'john',text: 'You ugly'},{name: 'john',text: 'You handsome'},{name: 'john',text: 'you beautiful'}],'fourth': [{name: 'tom',text: 'this is cool!'},{name: 'tom',text: 'this is hard'}]};

let arr = Object.values(obj),
    result = [];
while ((arr = arr.filter(sub => sub.length)).length) {
    result.push(arr.map(sub => sub.shift()));
}
console.log(result);

  • Related