javascript - 合并“行”并将有序“列”添加到对象数组
问题描述
我有一个一直坚持的矩阵算法。
输入:
['Claudia', 'Monday', 'Ice cream', '5'],
['Claudia', 'Tuesday', 'Ice cream', '5'],
['Claudia', 'Thursday', 'Cake', '10'],
['Anna', 'Monday', 'Ice cream', '5'],
['Beatrice', 'Tuesday', 'Cake', '10'],
['Beatrice', 'Wednesday', 'Cake', '10'],
['Beatrice', 'Thursday', 'Ice cream', '5'],
['Beatrice', 'Thursday', 'Biscuit', '7']
预期输出:
['P', 'Claudia', '20'],
['D', '1', 'Monday', 'Ice cream', '5'],
['D', '2', 'Tuesday', 'Ice cream', '5'],
['D', '3', 'Thursday', 'Cake', '10'],
['P', 'Anna', '5'],
['D', '1', 'Monday', 'Ice cream', '5'],
['P', 'Beatrice', '32'],
['D', '1', 'Tuesday', 'Cake', '10'],
['D', '2', 'Wednesday', 'Cake', '10'],
['D', '3', 'Thursday', 'Ice cream', '5'],
['D', '4', 'Thursday', 'Biscuit', '7']
用一句话来说:
- 在同一个人的行顶部添加一个“人员”行,包含该人的姓名和总费用。
- 为购买的物品添加订购列表
这是我的代码:
const chai = require('chai')
const chaiAsPromised = require("chai-as-promised")
chai.use(chaiAsPromised)
const expect = chai.expect,
should = chai.should
// for each row, create a header and detail row
const makeHeaderDetail = obj => {
let result = []
obj.map(row => {
const name = row[0],
date = row[1],
item = row[2],
price = row[3]
// prepare header & detail
let header = new Array(`P`, name),
detail = new Array (`D`, date, item, price)
result.push(header)
result.push(detail)
})
return result
}
// remove duplicate headers
// error: this merges all D rows that have same values in col0 and col1
// it should merge only P rows
const removeDuplicate = (obj, col0, col1) => {
const result = obj.reduce((acc, cur) => {
const key = `${cur[col0]}|${cur[col1]}`
if (!acc[key]) acc[key] = cur
return acc
}, {})
return Object.values(result)
}
// return the expected output
const groupReport = async(obj) => {
let result = makeHeaderDetail(obj)
result = removeDuplicate(result, 0, 1)
return result
}
// input data
const groupReportInput = [
['Claudia', 'Monday', 'Ice cream', '5'],
['Claudia', 'Tuesday', 'Ice cream', '5'],
['Claudia', 'Thursday', 'Cake', '10'],
['Anna', 'Monday', 'Ice cream', '5'],
['Beatrice', 'Tuesday', 'Cake', '10'],
['Beatrice', 'Wednesday', 'Cake', '10'],
['Beatrice', 'Thursday', 'Ice cream', '5'],
['Beatrice', 'Thursday', 'Biscuit', '7']
]
// expected output data
const groupReportOutput = [
['P', 'Claudia', '20'],
['D', '1', 'Monday', 'Ice cream', '5'],
['D', '2', 'Tuesday', 'Ice cream', '5'],
['D', '3', 'Thursday', 'Cake', '10'],
['P', 'Anna', '5'],
['D', '1', 'Monday', 'Ice cream', '5'],
['P', 'Beatrice', '32'],
['D', '1', 'Tuesday', 'Cake', '10'],
['D', '2', 'Wednesday', 'Cake', '10'],
['D', '3', 'Thursday', 'Ice cream', '5'],
['D', '4', 'Thursday', 'Biscuit', '7']
]
const doIt = groupReport(groupReportInput)
console.log(doIt)
describe('groupReport', () => {
it('should return an object with merged P rows and ordered list D rows', done => {
expect(doIt).to.eventually.deep.equal(groupReportOutput).notify(done)
})
})
我目前的做法是:
- 为每个原始行添加一个“P”行和一个“D”行。成功。
- 删除所有重复的“P”行。我的函数当前删除“重复的”“P”行:P 行包含相同的 col1 值。
- 添加有序列表项。一直无法弄清楚这一点。
解决方案
我只想一步完成所有事情:
function group(array) {
const grouped = {};
for(const [name, date, item, price] of array) {
if(!grouped[name]) {
grouped[name] = {
head: ["P", name, 0],
entries: []
};
}
const { entries, head } = grouped[name];
entries.push(["D", entries.length + 1, date, item, price]);
head[2] += +price;
}
return Object.values(grouped).reduce((res, entry) => ([...res, entry.head, ...entry.entries]), []);
}
推荐阅读
- c# - 使用 xpath 时访问了错误的 xml 节点
- android-studio - Android Studio Flutter 插件的颜色选择器在哪里
- c# - System.AccessViolationException:C# .NET 和 C++ 应用程序之间的 shared_ptr
- ios - UIView bounds.applying 但有旋转
- c# - 基于接口实现的 LINQ 连接
- node.js - 减少nodejs内存使用
- xml - 如何使用 xslt 将一个 xml 文件的内容复制到另一个空 xml 文件
- sql-server - SQL Server 升级导致临时表重复
- java - 无法在端口 443 上启动 Apache Tomcat | 地址已被使用
- java - 哪些重构工具可以重命名 Java 类及其所有类似名称的实例?