首页 > 解决方案 > 合并“行”并将有序“列”添加到对象数组

问题描述

我有一个一直坚持的矩阵算法。

输入:

['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)
    })
})

我目前的做法是:

标签: javascriptarraysmatrix

解决方案


我只想一步完成所有事情:

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]), []);
}

推荐阅读