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
}
];
abyrne85
  • 1,370
  • 16
  • 33

3 Answers3

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)
Ashish Ranjan
  • 12,760
  • 5
  • 27
  • 51
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>
RobC
  • 22,977
  • 20
  • 73
  • 80
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);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209