【问题标题】:Grouping an array by multiple keys with Array.reduce()使用 Array.reduce() 通过多个键对数组进行分组
【发布时间】:2022-01-11 18:04:51
【问题描述】:

第一次写到这里,遇到如下问题。例如,我有以下数组:

const input = [
  {
    id: 1,
    date: "01-01-2021",
    source: "TT",
    metrics: { conversions: 10, cpl: 3 },
  },
  {
    id: 2,
    date: "01-01-2021",
    source: "TT",
    metrics: { conversions: 15, cpl: 3 },
  },
  {
    id: 3,
    date: "01-01-2021",
    source: "FB",
    metrics: { conversions: 15, cpl: 4 },
  },
  {
    id: 4,
    date: "01-01-2021",
    source: "FB",
    metrics: { conversions: 15, cpl: 4 },
  },
  {
    id: 5,
    date: "02-01-2021",
    source: "TT",
    metrics: { conversions: 5, cpl: 2 },
  },
  {
    id: 6,
    date: "02-01-2021",
    source: "TT",
    metrics: { conversions: 15, cpl: 2 },
  },
  {
    id: 7,
    date: "02-01-2021",
    source: "FB",
    metrics: { conversions: 25, cpl: 1 },
  },
  {
    id: 8,
    date: "02-01-2021",
    source: "FB",
    metrics: { conversions: 30, cpl: 1 },
  },
];

我需要得到一个按日期和来源分组的数组,其值将是特定日期的所有值的总和,例如如下结果:

const output = [
  {
    date: "01-01-2021",
    TT: 25,
    FB: 30,
  },
  {
    date: "02-01-2021",
    TT: 20,
    FB: 55,
  },
];

在我的解决方案中,我找到了唯一的键和日期,但不知道下一步该做什么。你能帮助我吗?示例代码:

const result = input.reduce((acc, current) => {
  const dateItem = acc.find((item) => item.date === current.date);
  const sources = input.map((item) => item.source).filter((value, index, self) => self.indexOf(value) === index);

  if (dateItem) {
    return [...acc.filter((i) => i.date !== current.date), { ...dateItem }];
  }

  return [...acc, { date: current.date }];
}, []);

【问题讨论】:

  • 请解释一下将输入转化为输出的具体逻辑,这里不清楚。

标签: javascript arrays reduce


【解决方案1】:

Array.reduceObject.values 将给出结果。

const input = [
  { id: 1, date: "01-01-2021", source: "TT", metrics: { conversions: 10, cpl: 3 }, },
  { id: 2, date: "01-01-2021", source: "TT", metrics: { conversions: 15, cpl: 3 }, },
  { id: 3, date: "01-01-2021", source: "FB", metrics: { conversions: 15, cpl: 4 }, },
  { id: 4, date: "01-01-2021", source: "FB", metrics: { conversions: 15, cpl: 4 }, },
  { id: 5, date: "02-01-2021", source: "TT", metrics: { conversions: 5, cpl: 2 }, },
  { id: 6, date: "02-01-2021", source: "TT", metrics: { conversions: 15, cpl: 2 }, },
  { id: 7, date: "02-01-2021", source: "FB", metrics: { conversions: 25, cpl: 1 }, },
  { id: 8, date: "02-01-2021", source: "FB", metrics: { conversions: 30, cpl: 1 }, },
];
const output = input.reduce((acc, curr) => {
  if (acc[curr.date]) {
    acc[curr.date][curr.source] = (acc[curr.date][curr.source] || 0) + curr.metrics.conversions; 
  } else {
    acc[curr.date] = {
      date: curr.date,
      [curr.source]: curr.metrics.conversions
    }
  }
  return acc;
}, {});
console.log(Object.values(output));

【讨论】:

    【解决方案2】:

    使用日期作为键的简单化简循环。全部组合后,就可以使用值来获取数组了。

    const input = [{
        id: 1,
        date: "01-01-2021",
        source: "TT",
        metrics: {
          conversions: 10,
          cpl: 3
        },
      },
      {
        id: 2,
        date: "01-01-2021",
        source: "TT",
        metrics: {
          conversions: 15,
          cpl: 3
        },
      },
      {
        id: 3,
        date: "01-01-2021",
        source: "FB",
        metrics: {
          conversions: 15,
          cpl: 4
        },
      },
      {
        id: 4,
        date: "01-01-2021",
        source: "FB",
        metrics: {
          conversions: 15,
          cpl: 4
        },
      },
      {
        id: 5,
        date: "02-01-2021",
        source: "TT",
        metrics: {
          conversions: 5,
          cpl: 2
        },
      },
      {
        id: 6,
        date: "02-01-2021",
        source: "TT",
        metrics: {
          conversions: 15,
          cpl: 2
        },
      },
      {
        id: 7,
        date: "02-01-2021",
        source: "FB",
        metrics: {
          conversions: 25,
          cpl: 1
        },
      },
      {
        id: 8,
        date: "02-01-2021",
        source: "FB",
        metrics: {
          conversions: 30,
          cpl: 1
        },
      },
    ];
    
    
    const results = Object.values(input.reduce((o, data) => {
      o[data.date] = o[data.date] || { date: data.date };
      o[data.date][data.source] = (o[data.date][data.source] || 0) + data.metrics.conversions;
      return o;
    }, {}));
    console.log(results);

    【讨论】:

    • 非常感谢,我设法在您的解决方案中添加了日期属性,一切正常。对不起我的英语
    • 应该Object.values(...)Object.entries(...).map( [date,vals] => ({date,...vals}) )
    • 哎呀漏掉了o[data.date] = o[data.date] || { date: data.date };
    • 是的,我写了同一行。谢谢
    猜你喜欢
    • 2015-11-04
    • 2018-02-20
    • 2016-12-27
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 2020-10-21
    相关资源
    最近更新 更多