【问题标题】:Add new summary row for cols share the same vales of 2 different cols为 cols 添加新的汇总行共享 2 个不同列的相同值
【发布时间】:2018-06-13 20:16:30
【问题描述】:

我有一个矩阵算法:

输入:

const input = [
    ['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'],
    ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'],
    ['Camry', 'Toyota', 'Jan', 'Random City', '3000'],
    ['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'],
    ['Prius', 'Toyota', 'Jan', 'Random Town', '60'],
    ['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'],
    ['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'],
    ['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'],
    ['Civic', 'Honda', 'Mar', 'Random Town', '10'],
    ['Civic', 'Honda', 'Mar', 'Random Town', '20'],
]

预期输出:

const output = [
    ['S', 'Camry', 'Toyota', 'Jan', '3050'],
    ['D', 1, 'Camry', 'Nowhere Town', '50'],
    ['D', 2, 'Camry', 'Random City', '3000'],
    ['S', 'Camry', 'Toyota', 'Feb', '70'],
    ['D', 1, 'Camry', 'Nowhere Town', '70'],
    ['S', 'Prius', 'Toyota', 'Jan', '120'],
    ['D', 1, 'Prius', 'Nowhere Town', '60'],
    ['D', 2, 'Prius', 'Random Town', '60'],
    ['S', 'Prius', 'Toyota', 'Mar', '50'],
    ['D', 1, 'Prius', 'Nowhere Town', '50'],
    ['S', 'Civic', 'Honda', 'Jan', '10'],
    ['D', 1, 'Civic', 'Nowhere Town', '10'],
    ['S', 'Civic', 'Honda', 'Feb', '10'],
    ['D', 1, 'Civic', 'Nowhere Town', '10'],
    ['S', 'Civic', 'Honda', 'Mar', '20'],
    ['D', 1, 'Civic', 'Random Town', '10'],
    ['D', 2, 'Civic', 'Random Town', '10'],
]

言下之意: 如果行包含相同的 Brand、相同的 Make 和相同的 Month,则在顶部添加一个包含总销售额的摘要行,并为每个列添加列出的订单详细信息行。

我有一个旧代码:

const groupReport = arr => {
    let grouped = [].concat(...arr.reduce((acc, cur) => {
        var data = acc.get(cur[1]) || [['P', cur[1], '0']]
        data.push(['D', data.length, cur[0], cur[3], cur[4]])
        data[0][2] = (+data[0][2] + +cur[4]).toString()
        return acc.set(cur[0], data);
    }, new Map)
    .values()
    )
    return grouped
}

它不起作用,因为它只比较一个列(品牌),而不是制造和月份。

【问题讨论】:

标签: javascript arrays matrix


【解决方案1】:

您可以使用组合键和破坏数组。

var array = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'], ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'], ['Camry', 'Toyota', 'Jan', 'Random City', '3000'], ['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'], ['Prius', 'Toyota', 'Jan', 'Random Town', '60'], ['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'], ['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '20']],
    result = [].concat(...array
        .reduce((m, [brand, make, month, town, amount]) => {
            var key = [brand, make, month].join('|'),
                data = m.get(key) || [['S', brand, make, month, '0']];

            data.push(['D', data.length, brand, town, amount]);
            data[0][4] = (+data[0][4] + +amount).toString();
            return m.set(key, data);
        }, new Map)
        .values()
    );

console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 谢谢,@Nina Scholz!你又救了我!我可以在 LinkedIn 或 Twitter 上与您联系吗?
  • 抱歉,没有linkedin和twitter。
【解决方案2】:

您可以使用reduce 按品牌、品牌和月份创建对象,然后使用扩展语法和Object.values 获取数组数组。

const input = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'],['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'],['Camry', 'Toyota', 'Jan', 'Random City', '3000'],['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'],['Prius', 'Toyota', 'Jan', 'Random Town', '60'],['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'],['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'],['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'],['Civic', 'Honda', 'Mar', 'Random Town', '10'],['Civic', 'Honda', 'Mar', 'Random Town', '20'],]

const obj = input.reduce((r, [brand, make, month, city, value]) => {
  let key = `${brand}|${make}|${month}`;
  if(!r[key]) r[key] = [
    ['S', brand,  make, month, +value],
    ["D", 1, make, city, value]
  ]
  else {
    r[key][0][4] += +value;
    let prev = r[key].slice(-1)[0]
    r[key].push(["D",  prev[1] + 1, make, city, value]);
  }
  return r;
}, {})

const result = [].concat(...Object.values(obj))

console.log(result)

【讨论】:

  • 谢谢,@Nenad Vracar!我可以在 LinkedIn 或 Twitter 上与您联系吗?
【解决方案3】:

以下中断分两步进行输入。它大量使用了 es6 特性 Map 和扩展运算符。

第一步通过生成键值对将项目转换为组,然后将每个项目添加到由生成的键作为键的项目数组的 Map 中。

第二步从每个组中获取值来创建一个标题,然后他们创建一个以标题作为第一项的新数组。然后将这些组组合成一个数组。

const input = [['Camry', 'Toyota', 'Jan', 'Nowhere Town', '50'], ['Camry', 'Toyota', 'Feb', 'Nowhere Town', '70'], ['Camry', 'Toyota', 'Jan', 'Random City', '3000'], ['Prius', 'Toyota', 'Jan', 'Nowhere Town', '60'], ['Prius', 'Toyota', 'Jan', 'Random Town', '60'],    ['Prius', 'Toyota', 'Mar', 'Nowhere Town', '50'],    ['Civic', 'Honda', 'Jan', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Feb', 'Nowhere Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '10'], ['Civic', 'Honda', 'Mar', 'Random Town', '20']]

const group = new Map();
input.map(x => [ x.slice(0,3).join('::'), ['D', ...x.slice(0,4), +x[4]] ])
  .forEach(([key, val]) => (group.get(key) || group.set(key, []).get(key)).push(val));

const result = [].concat(... Array.from(group.values())
  .map(x => [['S', ...x[0].slice(1,4), x.reduce((a, c) => a + c[5], 0)], 
  	...x.map(y => [...y.slice(0, 3), ... y.slice(4,6)])]));

console.log(result.map(x => x.toString()));

【讨论】:

    猜你喜欢
    • 2018-11-29
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多