2

I discovered _.reduce however it only keeps 1 of set of information. What option should be used to combine like information?

[
  {
    fruit: 'apple',
    'color': 'red'
  },
  {
    fruit: 'apple',
    'color': 'green'
  },
  {
    fruit: 'pear',
    'color': 'yellow'
  },
  {
    fruit: 'pear',
    'color': 'green'
  }
]

My desired outcome would be:

var items = [
  {
    fruit: 'apple',
    'color': 'red', 'green'
  },
  {
    fruit: 'pear',
    'color': 'green', 'yellow'
  }
]

The current code I have using NodeJS is:

 let result = Object.values(json.reduce((c, {fruit,...r}) => {
   c[fruit] = c[fruit] || {fruit};
   c[fruit] = Object.assign(c[fruit], r);
   return c;
 }, {}));
1
  • 1
    Since you're using lodash, look into _.groupBy. You may need an additional post processing step to achieve your final data structure, but _.groupBy does a lot of the work. Commented Mar 2, 2020 at 2:58

3 Answers 3

2

This is an approach that runs in time O(n) instead of O(n^2):

const arr = [
  {
    fruit: 'apple',
    'color': 'red',
  },
  {
    fruit: 'apple',
    'color': 'green',
  },
  {
    fruit: 'pear',
    'color': 'yellow',
  },
  {
    fruit: 'pear',
    'color': 'green',
  },
];
const map = arr.reduce((acc, o) => {
  if (acc[o.fruit]) {
    acc[o.fruit].push(o.color);
  } else {
    acc[o.fruit] = [o.color];
  }
  return acc;
}, {});
const result = Object.keys(map).map(k => ({ fruit: k, colors: map[k] }));
console.log(result);
return result;

Note that, as noted in Nick's answer, the difference won't make a difference for a small array, but if the array is large, or the transformation is itself wrapped in a loop, it may matter.

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

Comments

1

You can use the Array reduce method for this. Assuming your array isn't super long, using the find method on each iteration shouldn't be too expensive. If it's a super long array, you might instead opt for an intermediate object that has hash table efficiency. Probably not necessary, though.

const arr = [
  {
    fruit: 'apple',
    'color': 'red'
  },
  {
    fruit: 'apple',
    'color': 'green'
  },
  {
    fruit: 'pear',
    'color': 'yellow'
  },
  {
    fruit: 'pear',
    'color': 'green'
  }
];

const combined = arr.reduce((acc, el) => {
  const fruit = acc.find(item => item.fruit === el.fruit);
  if (fruit) {
    fruit.colors.push(el.color)
  } else {
    acc.push({ fruit: el.fruit, colors: [el.color] });
  }
  return acc;
}, []);

console.log(combined);

Comments

0

Use simple forEach and build the object of unique keys and get the values using Object.values.

const data = [
  {
    fruit: "apple",
    color: "red"
  },
  {
    fruit: "apple",
    color: "green"
  },
  {
    fruit: "pear",
    color: "yellow"
  },
  {
    fruit: "pear",
    color: "green"
  }
];

const res = {};

data.forEach(
  item =>
    (res[item.fruit] =
      item.fruit in res
        ? { ...res[item.fruit], color: [...res[item.fruit].color, item.color] }
        : { fruit: item.fruit, color: [item.color] })
);

const output = Object.values(res);

console.log(output);

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.