3
const myObj = {
 a: [1, 2, 3],
 b: [2, 4, 6],
 c: [10, 20, 30]
}

Into

const myCollection = [
  {a: 1, b: 2, c: 10},
  {a: 2, b: 4, c: 20},
  {a: 3, b: 6, c: 30}
]

I tried combinations of Object.entries, Object.keys and map but I'm always finding myself iterating twice or more over myObj and I'm not happy with any solution I came up with. So what is the most efficient (in terms of time complexity) and elegant way that you can think to achieve that?

1
  • 1
    Please share the code you've tried. Also some details are needed, does your A,B and C always have the same length? Commented Sep 30, 2020 at 10:53

5 Answers 5

1

Just in case you'd need variable length:

const myObj = {
  a: [1, 2, 3],
  b: [2, 4, 6,8, 10],
  c: [10, 20, 30, 40],
};

let myCollection = [];

Object.keys(myObj).forEach((k) => {
  for (let i = 0; i < myObj[k].length; i++) {
    if (!myCollection[i]) myCollection.push({});
    myCollection[i][k] = myObj[k][i];
  }
});
console.log(myCollection);

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

Comments

0

You could reduce the entries and map nested arrays.

const
    object = { a: [1, 2, 3], b: [2, 4, 6], c: [10, 20, 30] },
    result = Object
        .entries(object)
        .reduce((r, [k, a]) => a.map((v, i) => ({ ...r[i], [k]: v })), []);

console.log(result);

Comments

0

That can be done using Array.reduce. I have attached the conversion code.

const myObj = {
 a: [1, 2, 3],
 b: [2, 4, 6],
 c: [10, 20, 30]
}

const myCollection = [
  {a: 1, b: 2, c: 10},
  {a: 2, b: 4, c: 20},
  {a: 3, b: 6, c: 30}
]

const maxLength = Math.max(...Object.values(myObj).map(item => item.length));

const myObjKeys = Object.keys(myObj);
const result = [ ...Array(maxLength).keys() ].map((index) => {
  return myObjKeys.reduce((acc, curKey) => {
    if (myObj[curKey].length > index) {
      acc[curKey] = myObj[curKey][index];
    }
    return acc;
  }, {});
});
console.log(result);

Comments

0

Using ramdajs, I could suggest you a short way like below

const myObj = {
  a: [1, 2, 3],
  b: [2, 4, 6],
  c: [10, 20, 30]
}

const res = R.map(
  R.zipObj(R.keys(myObj)),
  R.values(myObj)
)

console.log(res)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

In ramdajs homepage, criteria 3 in What's Different, it cited that

The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.

1 Comment

Thumbs up for elegancy, but I'm not using Ramda. But it did gave me a direction of how to achieve the same with Lodash (almost the same functions)
0

You can use map() on Object.values and then use reduce() on each value.

const myObj = {
 a: [1, 2, 3],
 b: [2, 4, 6],
 c: [10, 20, 30]
}

let keys = Object.keys(myObj);
const arr = Object.values(myObj).map((a) => a.reduce((ac, a, i) => ({...ac, [keys[i]]:a}), {}));
console.log(arr)

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.