0

How would I turn an array of objects like this

const scores = [
{
   year: 2020,
   dave: 20
},
{
   year: 2020,
   steve: 17
},
{
   year: 2019,
   bill: 18
}
];

into this

const scores = [
{
   year: 2020,
   dave: 20,
   steve: 17
},
{
   year: 2019,
   bill: 18
}
];
3
  • 1
    maybe this helps stackoverflow.com/questions/14446511/… Commented May 8, 2020 at 15:24
  • GroupBy! I couldn't remember the term Commented May 8, 2020 at 15:24
  • You might lose some data in case there are multiple objects with same year and same keys. Commented May 8, 2020 at 15:55

3 Answers 3

1

I used an Array.reduce() and to have an Object with keys as year and kept assigning the Objects, later took out the values.

const scores = [
  {
     year: 2020,
     dave: 20
  },
  {
     year: 2020,
     steve: 17
  },
  {
     year: 2019,
     bill: 18
  }
];

const mergedOb = scores.reduce((acc, ob) => {
  if (acc[ob.year]) {
    Object.assign(acc[ob.year], ob);
  } else {
    acc[ob.year] = ob
  }
  return acc;
}, {});

const mergeArr = Object.values(mergedOb)
console.log(mergeArr)

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

Comments

1

Are you looking for this?

<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
  <script>
    $(function () {
        const scores = [
            {
                year: 2020,
                dave: 20
            },
            {
                year: 2020,
                steve: 17
            },
            {
                year: 2019,
                bill: 18
            }
        ];

        var groupBy = function (xs, key) {
            return xs.reduce(function (rv, x) {
                (rv[x[key]] = rv[x[key]] || []).push(x);
                return rv;
            }, {});
        };

        console.log(groupBy(scores, 'year'));
    })
</script>
</body>
</html>

Comments

0

You can create a function with _.flow() that uses _.groupBy() to collect items with the same year to arrays, and then maps and merges the arrays:

const { flow, groupBy, map, merge } = _;;

const fn = flow(
  arr => groupBy(arr, 'year'),
  groups => map(groups, g => merge({}, ...g))
);

const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];

const result = fn(scores);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Using lodash/fp makes this solution even more concise:

const fn = flow(
  groupBy('year'),
  map(mergeAll)
);

const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];

const result = fn(scores);

console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

However, since _.mergeBy() creates an object, grouping by a number, will change the order of the groups (2020 after 2019). You can reduce the array to a Map to preserve the order, and then convert it to an array by spreading the Map's value iterator:

const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];

const result = [...scores.reduce((r, o) => 
  r.set(o.year, { ...r.get(o.year), ...o })
, new Map()).values()];

console.log(result);

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.