【问题标题】:JavaScript Array: Query an array by 2 grouping: stuck in a reduce() javascript problemJavaScript 数组:按 2 分组查询数组:卡在 reduce() javascript 问题中
【发布时间】:2020-04-24 10:31:52
【问题描述】:

reduce() 函数有问题。

假设我有这个数组:

myOrders = 
  [ { order_date: '2019/12/01', order_type: 'Shoes',  order_amount: 50 } 
  , { order_date: '2019/12/01', order_type: 'Shoes',  order_amount: 30 } 
  , { order_date: '2019/12/01', order_type: 'Shirts', order_amount: 30 } 
  , { order_date: '2019/12/02', order_type: 'Shoes',  order_amount: 10 } 
  ] 

我需要想出类似下面的东西:

    filteredOrders = [
       {
        order_date: '2019/12/01',
        ordered_items: {
           {type: 'Shoes', amount: 80},
           {type: 'Shirts', amount: 30}
        }
      }
    ]

请注意,此过滤后的数组正在查询 date 并将 amounttype 相加。

我有以下代码,但考虑到type,我无法使其工作

let seriesData = Object.entries(
  buyOperations.reduce(
    (dvs, { order_date: d, order_amount: v }) => 
      ({ ...dvs, [d]: (dvs[d] || 0) + v }), {}
    )
  ).map(([order_date, order_amount]) => ({
      order_date,
      order_amount
  }));

【问题讨论】:

  • filteredOrders[0].ordered_items 不能是一个对象,但应该是一个数组?
  • buyOperations来自哪里???
  • 这只是示例代码。
  • stackoverflow.com/help/how-to-ask +最好有一致性。

标签: javascript arrays ecmascript-6 mapreduce reduce


【解决方案1】:

您可以使用reduce 方法对order_date 进行分组,然后根据order_type 是否已推送,您可以对元素进行求和:

myOrders.reduce((a, {order_date, order_type,order_amount})=> {
    a[order_date] = a[order_date] || {order_date, ordered_items: []};

    let order_items = a[order_date].ordered_items.find(s => s.type == order_type);
    if (order_items)
        order_items.amount +=order_amount;
    else
        a[order_date].ordered_items.push({type: order_type, amount: order_amount});

    return a;    
}, {})

一个例子:

let myOrders =  [
        {
            order_date: '2019/12/01',
            order_type: 'Shoes',
            order_amount: 50
        },
        {
            order_date: '2019/12/01',
            order_type: 'Shoes',
            order_amount: 30
        },
        {
            order_date: '2019/12/01',
            order_type: 'Shirts',
            order_amount: 30
        },
        {
            order_date: '2019/12/02',
            order_type: 'Shoes',
            order_amount: 10
        }
    ];    

const result = myOrders.reduce((a, {order_date, order_type,order_amount})=> {
    a[order_date] = a[order_date] || {order_date, ordered_items: []};
    let order_items = a[order_date].ordered_items.find(s => s.type == order_type);
    if (order_items)
        order_items.amount +=order_amount;
    else
        a[order_date].ordered_items.push({type: order_type, amount: order_amount});        
    return a;
}, {})

console.log(`filtered array: `, Object.values(result).filter(f => f.order_date == '2019/12/01'));
console.log(`overall array: `, Object.values(result));

【讨论】:

    【解决方案2】:

    您需要按 dae 和类型进行嵌套分组。这种方法对数据使用单个循环,并使用Array#find 获取相同的组。如果未找到,则将新组插入同一级别。

    var orders = [{ order_date: '2019/12/01', order_type: 'Shoes', order_amount: 50 }, { order_date: '2019/12/01', order_type: 'Shoes', order_amount: 30 }, { order_date: '2019/12/01', order_type: 'Shirts', order_amount: 30 }, { order_date: '2019/12/02', order_type: 'Shoes', order_amount: 10 }],
        grouped = orders.reduce((r, { order_date, order_type, order_amount }) => {
            var date = r.find(q => q.order_date === order_date);
            if (!date) r.push(date = { order_date, ordered_items: [] });
            var type = date.ordered_items.find(q => q.order_type === order_type);
            if (!type) date.ordered_items.push(type = { order_type, order_amount: 0 });
            type.order_amount += order_amount;
            return r;
        }, []);
    
    console.log(grouped);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2011-05-04
      相关资源
      最近更新 更多