我有一个对象数组如下:
(line < 0) and (test == 1)
我希望按( [
{"id":1,"lib":"A","categoryID":10,"categoryTitle":"Cat10","moduleID":"2","moduleTitle":"Module 2"},
{"id":2,"lib":"B","categoryID":10,"categoryTitle":"Cat10","moduleID":"2","moduleTitle":"Module 2"},
...
{"id":110,"lib":"XXX","categoryID":90,"categoryTitle":"Cat90","moduleID":"4","moduleTitle":"Module 4"}
]
,moduleID
)然后按(moduleTitle
,categoryID
)对此数组进行分组。
这就是我的尝试:
categoryTitle
上面的代码按预期工作,但正如您所看到的,在第一次分组之后,我不得不再次遍历由function groupBy(data, id, text) {
return data.reduce(function (rv, x) {
var el = rv.find(function(r){
return r && r.id === x[id];
});
if (el) {
el.children.push(x);
} else {
rv.push({ id: x[id], text: x[text], children: [x] });
}
return rv;
}, []);
}
var result = groupBy(response, "moduleID", "moduleTitle");
result.forEach(function(el){
el.children = groupBy(el.children, "categoryID", "categoryTitle");
});
分组的数组,以便按moduleId
进行分组
如何修改此代码,以便我只能在阵列上调用categoryId
函数一次?
对不起,这可能会迟到,但我想通过使用ES5,没有Shim和没有Polyfill来完成这项工作。
答案 0 :(得分:2)
这是一种可能的(尽管可能有点高级)方法:
class DefaultMap extends Map {
constructor(factory, iter) {
super(iter || []);
this.factory = factory;
}
get(key) {
if (!this.has(key))
this.set(key, this.factory());
return super.get(key);
}
}
基本上,它是一个Map
,它在缺少值时调用工厂函数。现在,有趣的部分:
let grouper = new DefaultMap(() => new DefaultMap(Array));
for (let item of yourArray) {
let firstKey = item.whatever;
let secondKey = item.somethingElse;
grouper.get(firstKey).get(secondKey).push(item);
}
对于每个firstKey
,这会在Map
内创建grouper
,这些地图的值是按第二个键分组的数组。
你问题的一个更有趣的部分是你正在使用复合键,这在JS中非常棘手,因为它提供(几乎)不可变的数据结构。考虑:
items = [
{a: 'one', b: 1},
{a: 'one', b: 1},
{a: 'one', b: 2},
{a: 'two', b: 2},
]
let grouper = new DefaultMap(Array);
for (let x of items) {
let key = [x.a, x.b]; // wrong!
grouper.get(key).push(x);
}
因此,我们通过复合键天真地对对象进行分组,并希望在我们的石斑鱼中看到['one', 1]
下的两个对象(为了示例,这是一个级别)。当然,这不起作用,因为每个key
都是一个新创建的数组,并且Map
或任何其他键控存储都有所不同。
一种可能的解决方案是为每个密钥创建一个不可变结构。一个明显的选择是使用Symbol
,例如
let tuple = (...args) => Symbol.for(JSON.stringify(args))
然后
for (let x of items) {
let key = tuple(x.a, x.b); // works
grouper.get(key).push(x);
}
答案 1 :(得分:1)
你可以这样做:
const grouped = groupBy(response, "moduleID", "moduleTitle");
console.log( grouped[2]["workflow"][exit] );
所以你可以像访问它一样访问它:
class EnergyModel:
__init__(self):
# set breakpoint
import pdb; pdb.set_trace()
...
您可以放弃退出符号,但将嵌套树与数组混合会感觉有点不对。
答案 2 :(得分:1)
您可以使用数组作为分组ID /名称来扩展您的功能。
function groupBy(data, groups) {
return data.reduce(function (rv, x) {
groups.reduce(function (level, key) {
var el;
level.some(function (r) {
if (r && r.id === x[key[0]]) {
el = r;
return true;
}
});
if (!el) {
el = { id: x[key[0]], text: x[key[1]], children: [] };
level.push(el);
}
return el.children;
}, rv).push({ id: x.id, text: x.lib });
return rv;
}, []);
}
var response = [{ id: 1, lib: "A", categoryID: 10, categoryTitle: "Cat10", moduleID: "2", moduleTitle: "Workflow" }, { id: 2, lib: "B", categoryID: 10, categoryTitle: "Cat10", moduleID: "2", moduleTitle: "Module 2" }, { id: 110, lib: "XXX", categoryID: 90, categoryTitle: "Cat90", moduleID: "4", moduleTitle: "Module 4" }],
result = groupBy(response, [["moduleID", "moduleTitle"], ["categoryID", "categoryTitle"]]);
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
路径为id
的版本。
function groupBy(data, groups) {
return data.reduce(function (rv, x) {
var path = [];
var last = groups.reduce(function (level, key, i) {
path.length = i;
path[i] = key[0].slice(0, -2).toUpperCase() + ':' + x[key[0]];
var id = path.join(';'),
el = level.find(function (r) {
return r && r.id === id;
});
if (!el) {
el = { id: path.join(';'), text: x[key[1]], children: [] };
level.push(el);
}
return el.children;
}, rv);
last.push({ id: path.concat('NODE:' + x.id).join(';') });
return rv;
}, []);
}
var response = [{ id: 1, lib: "A", categoryID: 10, categoryTitle: "Cat10", moduleID: "2", moduleTitle: "Workflow" }, { id: 2, lib: "B", categoryID: 10, categoryTitle: "Cat10", moduleID: "2", moduleTitle: "Module 2" }, { id: 110, lib: "XXX", categoryID: 90, categoryTitle: "Cat90", moduleID: "4", moduleTitle: "Module 4" }];
var result = groupBy(response, [["moduleID", "moduleTitle"], ["categoryID", "categoryTitle"]]);
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;