合并"行"并添加有序" cols"对象数组

时间:2018-05-24 14:08:32

标签: javascript arrays matrix

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

输入:

['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' rows:P行包含相同的col1值。
  • 添加有序列表项。避风港能够解决这个问题。

2 个答案:

答案 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; }