ES6 映射和减少频率计数

ES6 Mapping and reducing frequency count

我有一个 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 功能实现上述输出?

谢谢

第一步是使用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'))