如何通过主键对数组的所有数据项进行分组并将组的所有剩余条目收集为分组值列表来重组数组的所有数据项?

How to restructure all data-items of an array by grouping them via main-key and collecting all of a group's remaining entries as grouped value-lists?

我在按键合并数组中的对象以及对数组中具有相同键的值进行分组时遇到问题。示例:

let a = [{
    key: "1",
    value: "a",
    value2: "b"
}, {
    key: "2",
    value: "a",
    value2: "b"
}, {
    key: "1",
    value: "b",
    value2: "a"
}, {
    key: "1",
    value: "c",
    value2: "d"
}]

我想要达到的结果是:

[{
    key: "1",
    value: ["a", "b", "c"],
    value2: ["b", "a", "d"]
}, {
    key: "2",
    value: ["a"],
    value2: ["b"]
}]

在 javascript/typescript 中有人对此有简单的解决方案吗?

我已经阅读了很多关于类似问题的帖子,但是 none 与我上面的完全相同。

提前致谢!

你可以这样试试。它首先将数据缩减为基于键的对象,然后将其转换为您的数组。

var a = [{key:"1", value:"a",value2:"b"}, {key:"2", value:"a",value2:"b"}, {key:"1", value:"b",value2:"a"},{key:"1", value:"c",value2:"d"}]

a = a.reduce((acc, curr) => {
  if (!acc[curr.key]) {
    acc[curr.key] = { value: [curr.value], value2: [curr.value2] };
  } else {
    acc[curr.key].value.push(curr.value);
    acc[curr.key].value2.push(curr.value2);
  }
  
  return acc;
}, {});

a = Object.entries(a).map(([key, value]) => ({ key, ...value }))

console.log(a);

let a = [{key:"1", value:"a",value2:"b"}, {key:"2", value:"a",value2:"b"}, {key:"1", value:"b",value2:"a"},{key:"1", value:"c",value2:"d"}]

const result = a.reduce((res, item) => {
  let trans = res.find(e => e.key === item.key) || res.push(item) && item ;
  Object.entries(item).map(([key, val]) => {
      if(key !== "key") {
        trans[key] = Array.isArray(trans[key]) ? [...trans[key], val]: [val];
      }
    });
  return res;
}, []);

console.log('result', result);

通用方法的实现方式是仅考虑常见转换任务的主要数据结构。它始终不知道(最终)分组键,但它确实为后者实现了一个配置选项。

因此,有人可能想出一种基于两种 reduce 方法的方法,一种用于按提供的组 -key 值收集组,另一种用于将条目值收集到(分组)列表 ...

function collectEntryValueAsListItem(accumulator, entry) {
  const [key, value] = entry;

  const valueList = accumulator[key] || (accumulator[key] = []);
  valueList.push(value);

  return accumulator;
}
function groupDataByKeyAndCollectEntryValues(collector, item) {
  const { key, index, list } = collector;
  const groupKey = item[key];

  let groupItem = index[groupKey];
  if (!groupItem) {

    groupItem = index[groupKey] = { [key]: groupKey };
    list.push(groupItem);
  }
  item = Object.assign({}, item);
  delete item[key];

  Object
    .entries(item)
    .reduce(collectEntryValueAsListItem, groupItem);

  return collector;
}


const sampleList = [
  { key: "1", value: "a", value2: "b" },
  { key: "2", value: "a", value2: "b" },
  { key: "1", value: "b", value2: "a" },
  { key: "1", value: "c", value2: "d" },
];

console.log(
  '... the result which the OP was looking for ...',
  sampleList.reduce(groupDataByKeyAndCollectEntryValues, {

    key: 'key',
    index: {},
    list: [],

  }).list
);

console.log(
  '... 2nd proof of the generic reduce approach ...',
  sampleList.reduce(groupDataByKeyAndCollectEntryValues, {

    key: 'value',
    index: {},
    list: [],

  }).list
);
console.log(
  '... 3rd proof of the generic reduce approach ...',
  sampleList.reduce(groupDataByKeyAndCollectEntryValues, {

    key: 'value2',
    index: {},
    list: [],

  }).list
);
.as-console-wrapper { min-height: 100%!important; top: 0; }