我有一个这样的对象数组:
[
{ name: "Group 1", value: "Foo" },
{ name: "Group 2", value: "Bar" },
{ name: "Group 1", value: "Baz" }
]
我想使用Partial Lenses库将这些组转换为具有相应组项目的对象的键,如下所示:
{
"Group 1": [
{ name: "Group 1", value: "Foo" },
{ name: "Group 1", value: "Baz" }
],
"Group 2": [
{ name: "Group 2", value: "Bar" }
]
}
我当前的方法是这样的,假设我将源数据存储在名为data
的变量中:
const grouped = L.collect([L.groupBy('name'), L.entries], data)
const setKey = [L.elems, 0]
const getName = [L.elems, 1, 0, 'name']
const correctPairs = L.disperse(setKey, L.collectTotal(getName, grouped), grouped)
L.get(L.inverse(L.keyed), correctPairs)
我不喜欢我需要使用grouped
和correctPairs
变量来保存数据,因为我可能应该能够直接在合成中进行转换。您能帮我以更有意义的方式组合相同的功能吗?
这是上面代码的Partial Lenses Playground。
答案 0 :(得分:2)
我认为目标是实际创建同构,通过它可以
将这样的数组视为数组的对象,并执行更新。像一个
的双向版本拉姆达
R.groupBy
功能。
实际上,一种方法是只使用Ramda的
R.groupBy
实现新的原语
L.iso
使用同构。
像这样:
const objectBy = keyL => L.iso(
R.cond([[R.is(Array), R.groupBy(L.get(keyL))]]),
R.cond([[R.is(Object), L.collect([L.values, L.elems])]])
)
需要条件,以允许数据不是
预期的类型,并在不存在的情况下将结果映射到undefined
。
这里是a playground with the above Ramda based
objectBy
实施。
仅使用当前版本的偏光镜片,一种构成类似镜片的方法
objectBy
组合器如下:
const objectBy = keyL => [
L.groupBy(keyL),
L.array(L.unzipWith1(L.iso(x => [L.get(keyL, x), x], L.get(1)))),
L.inverse(L.keyed)
]
也许上面有趣的部分是转换
将数组数组转换为键数组对数组(或者相反)。
L.unzipWith1
检查组中的所有键是否匹配,如果不匹配,则检查该组
将被映射到undefined
并被过滤掉
L.array
。如果需要的话
可以通过使用更严格的行为
L.arrays
。
答案 1 :(得分:1)
您可以使用Array.reduce
let arr = [{ name: "Group 1", value: "Foo" },{ name: "Group 2", value: "Bar" },{ name: "Group 1", value: "Baz" }];
let obj = arr.reduce((a,c) => Object.assign(a, {[c.name]: (a[c.name] || []).concat(c)}), {});
console.log(obj);
答案 2 :(得分:1)
您不需要任何库,可以使用返回归约函数的泛型函数,从而可以使用任何键对任何集合进行分组。在下面的示例中,我用它来按名称分组,但也按值分组。
const groupBy = key => (result,current) => {
let item = Object.assign({},current);
// optional
// delete item[key];
if (typeof result[current[key]] == 'undefined'){
result[current[key]] = [item];
}else{
result[current[key]].push(item);
}
return result;
};
const data = [{ name: "Group 1", value: "Foo" },{ name: "Group 2", value: "Bar" },{ name: "Group 1", value: "Baz" }];
const grouped = data.reduce(groupBy('name'),{});
console.log(grouped);
const groupedByValue = data.reduce(groupBy('value'),{});
console.log(groupedByValue);