不可变js的递归分组

Recursive grouping with immutable js

var list = new List([
  { "col1": "1", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "A", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "B", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "C", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "1", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "A", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "B", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "C", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "2", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "A", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "B", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "B", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "C", "col3": "cat", "col4": "dog", "col5": "blue"},
  { "col1": "3", "col2": "C", "col3": "bird", "col4": "dog", "col5": "blue"},
  { "col1": "4", "col2": "A", "col3": "cat", "col4": "dog", "col5": "blue"}
  ]);

let groupedData = list.groupBy(x => x['col1'])
  .map(row => row.groupBy(x => x['col2'])
       .map(row => row.groupBy(x => x['col3']))
   );

这将按 col1、col2 和 col3 创建三个级别的分组。

我将如何使用任何 n 列进行分组并按任何顺序(例如 [coln, col4, coln-1],)递归地执行此操作?

一种方法是仅将第一个 groupBy 调用分配给 groupedData,然后在其上 运行 DFS,每次分配一个 groupBy 调用给每个您所在级别的单元格。这将改变初始 groupedData 的内部结构,但我认为您的代码已经做到了。

类似于(未测试):

function dfs(row, i, n){
  if (i > n)
    return;

  for (let j=0; j<row.length; j++){
    row[j] = row.groupBy(x => x['col' + i]);
    dfs(row[j], i + 1, n);
  }
}

let n = ???

let groupedData = list.groupBy(x => x['col1']);

for (row of groupedData)
  dfs(row, 2, n);

针对表示 table 数据的 immutable.js 列表对象进行递归分组的测试答案:

recursiveGrouping = (columns, list) => {
    columns.forEach(column => {
        list = this.processIterable(column, list);
    })
    return list;
}

processIterable = (column, iterable) => {
    if(List.isList(iterable)) return iterable.groupBy(row => row[column]);
    else if(Map.isMap(iterable)) return iterable.map(value => this.processIterable(column, value));
    else return iterable;
}

根据我上面的示例,我将使用这些方法进行调用:

let grouped data = this.recursiveGrouping(['col1', 'col2', 'col3'], list);

这returns与手动调用子分组相同的分组。