Объединить массив объектов на основе значения ключа - PullRequest
0 голосов
/ 08 мая 2020

Как мне превратить массив таких объектов

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

в этот

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

Ответы [ 3 ]

1 голос
/ 08 мая 2020

Вы это ищете?

<!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>
1 голос
/ 08 мая 2020

Я использовал Array.reduce () и чтобы иметь объект с ключами как год и продолжал назначать объекты, позже вынул значения.

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)
0 голосов
/ 08 мая 2020

Вы можете создать функцию с _.flow(), которая использует _.groupBy() для сбора элементов с одинаковыми year в массивы, а затем сопоставляет и объединяет массивы:

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>

Использование lodash / fp делает это решение еще более кратким:

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>

Однако, поскольку _.mergeBy() создает объект, группировка по номеру изменит порядок групп (2020 г. после 2019 г.). Вы можете уменьшить массив до Map, чтобы сохранить порядок, а затем преобразовать его в массив, расширив итератор значений Map:

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);
...