我有一个我一直坚持使用的矩阵算法。
输入:
['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)
})
})
我目前的做法是:
答案 0 :(得分:1)
我只需一步完成所有事情:
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]), []);
}
答案 1 :(得分:1)
您可以为每个Map
的人使用单个数组,并在分组后获取值。
var array = [['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']],
result = [].concat(...array
.reduce((m, [person, day, type, amount]) => {
var data = m.get(person) || [['P', person, '0']];
data.push(['D', data.length, day, type, amount]);
data[0][2] = (+data[0][2] + +amount).toString();
return m.set(person, data);
}, new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }