不可变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与手动调用子分组相同的分组。
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与手动调用子分组相同的分组。