ES6映射并减少频率计数

时间:2019-01-07 21:15:21

标签: javascript mapreduce es6-modules

我有一个csv文件,其中包含以下格式的数据(尽管有更多数据)。

ID      COL1        COL2        COL3        COL4
-----------------------------------------------------------
1       opt1        opt1        opt1        opt1
-----------------------------------------------------------
2       opt2        opt2        opt2        opt2
-----------------------------------------------------------
3       opt3        opt3        opt3        opt3
-----------------------------------------------------------
4       opt3        opt3        opt3        opt3
-----------------------------------------------------------
5       opt3        opt3        opt3        opt3
-----------------------------------------------------------
6       opt2        opt2        opt3        opt3
-----------------------------------------------------------
7       opt4        opt2        opt2        opt2
-----------------------------------------------------------
8       opt1        opt1        opt1        opt1
-----------------------------------------------------------
9       opt2        opt5        NA          NA
-----------------------------------------------------------

我将此数据传递到数组中。我想做的是仅在第一列中计算值的频率。因此,目前,我定义了一个选项列表

let labels = ["opt1", "opt2", "opt3", "opt4"];
let data = [];

然后我有一个计算钥匙的功能

function countByKey (array, column, keyValue) {
    let sum = 0;
    for (let i = 0, len = array.length; i < len; i++) {
        if (array[i][column] === keyValue) {
            sum += 1;
        }
    }
    return sum;
}

最后是输出频率的部分

for (let i in this.labels) {
    data.push({
        "Label": this.labels[i],
        "Frequency": this.countByKey(this.csv, "COL1", this.labels[i])
    });
}

这很好,我最终得到类似的东西

[
    {
       Label: opt1
       Frequency: 42
    },
    {
       Label: opt2
       Frequency: 108
    },
    ...
]

但是,因为我现在在VueJS中使用ES6,所以我已经看到有更简单的方法可以做到这一点。一种方法似乎是使用Map和reduce。我已经尝试过了

let acc = this.csv.reduce((acc, val) => acc.set(val, 1 + (acc.get(val) || 0)), new Map());

但这似乎可以输出我所有的数据,并具有某种计数。如何使用ES6功能实现上述输出?

谢谢

1 个答案:

答案 0 :(得分:1)

第一步是使用reduce生成一个对象(或Map),该对象计算每个标签的频率。第二步是获取该对象并将其转换为所需的“标签/频率”对数组:

const csv = [
  {ID: 1, COL1: 'opt1', COL2: 'opt1', COL3: 'opt1', COL4: 'opt1'},
  {ID: 1, COL1: 'opt2', COL2: 'opt2', COL3: 'opt2', COL4: 'opt2'},
  {ID: 1, COL1: 'opt3', COL2: 'opt3', COL3: 'opt3', COL4: 'opt3'},
  {ID: 1, COL1: 'opt3', COL2: 'opt3', COL3: 'opt3', COL4: 'opt3'},
  {ID: 1, COL1: 'opt3', COL2: 'opt3', COL3: 'opt3', COL4: 'opt3'},
  {ID: 1, COL1: 'opt2', COL2: 'opt2', COL3: 'opt3', COL4: 'opt3'},
  {ID: 1, COL1: 'opt4', COL2: 'opt2', COL3: 'opt2', COL4: 'opt2'},
  {ID: 1, COL1: 'opt1', COL2: 'opt1', COL3: 'opt1', COL4: 'opt1'},
  {ID: 1, COL1: 'opt2', COL2: 'opt5', COL3: 'NA', COL4: 'NA'}
]

const countByCol = col => {
  const counts = csv.reduce((memo, row) => {
    memo[row[col]] = (memo[row[col]] || 0) + 1;
    return memo;
  }, {});
  return Object.entries(counts).map(([Label, Frequency]) => ({Label, Frequency}));
};

console.log(countByCol('COL1'))