具有 属性 功能的多级 groupby
multi level groupby with function on a property
这与 类似,但有一点给我带来麻烦。除了两级分组之外,我希望内部分组依据是 属性 值的处理版本。
考虑这样的数据:
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' } ];
我可以取出密钥,处理它并使其独一无二:
const getZoneFromName = n => join('-', slice(1, 3, split('-', n)));
uniq(map(getZoneFromName, pluck('name', data)));
这会让我得到一个不错的清单:
["key-a", "key-b", "key-c"]
我可以将列表分为两个级别:
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(prop("name")))
);
groupByTopThenZone(data);
但我不知道如何将它们组合起来以获得以下输出:
{
top1: {
"key-a": [
{
name: "junk-key-a-101",
top: "top1"
}
],
"key-b": [
{
name: "junk-key-b-102",
top: "top1"
}
]
},
top2: {
"key-c": [
{
name: "junk-key-c-103",
top: "top2"
},
{
name: "junk-key-c-104",
top: "top2"
}
]
}
}
我觉得我有点傻,我不能得到这个。有任何想法吗? Here是玩的地方
这不是使用 ramda,而是 vanilla JS。
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' } ];
const res = data.reduce((acc, val, ind, arr) => {
const top = val.top;
// if the top does not exist in the obj, create it
if (!acc[top]) {
acc[top] = {};
}
// get the key through split. you could also use a regex here
const keyFragments = val.name.split('-');
const key = [keyFragments[1], keyFragments[2]].join('-');
// if the key obj prop does not exist yet, create the array
if (!acc[top][key]) {
acc[top][key] = [];
}
// push the value
acc[top][key].push({ name: val.name, top: val.top });
return acc;
}, {});
console.log(res);
你们非常亲密。只需将这些函数与 compose
/pipe
结合起来就可以了。
(注意这里也是getZoneFromName
的简化版。)
const {pipe, groupBy, map, prop, slice} = R
//const getZoneFromName = n => join('-', slice(1, 3, split('-', n)));
const getZoneFromName = slice(5, -4)
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(pipe(prop("name"), getZoneFromName)))
)
const data = [{"name": "junk-key-a-101", "top": "top1"}, {"name": "junk-key-b-102", "top": "top1"}, {"name": "junk-key-c-103", "top": "top2"}, {"name": "junk-key-c-104", "top": "top2"}]
console.log(groupByTopThenZone(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
当然这个函数简化了那么多,内联它可能更容易:
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(pipe(prop("name"), slice(5, -4)))
)
要记住的主要事情是 groupBy
不一定与 prop
绑定。我们可以对 any String
/Number
/Symbol
生成函数的结果进行分组。
另一种方法是构建每个最终对象并将它们全部合并:
你可以转换这个对象:
{
"top": "top1",
"name": "junk-key-a-101"
}
进入这个:
{
"top1": {
"key-a": [
{
"name": "junk-key-a-101",
"top": "top1"
}
]
}
}
具有这些功能:
const key = slice(5, -4);
const obj = ({top, name}) => ({
[top]: {
[key(name)]: [
{top, name}
]
}
});
现在您可以迭代数据,转换每个对象并将它们合并在一起:
const groupByTopTenZone = reduce(useWith(mergeDeepWith(concat), [identity, obj]), {});
完整示例:
const {slice, useWith, identity, reduce, mergeDeepWith, concat} = R;
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' }
];
const key = slice(5, -4);
const obj = ({top, name}) => ({
[top]: {
[key(name)]: [
{top, name}
]
}
});
const groupByTopTenZone = reduce(useWith(mergeDeepWith(concat), [identity, obj]), {});
console.log(
groupByTopTenZone(data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
这与
考虑这样的数据:
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' } ];
我可以取出密钥,处理它并使其独一无二:
const getZoneFromName = n => join('-', slice(1, 3, split('-', n)));
uniq(map(getZoneFromName, pluck('name', data)));
这会让我得到一个不错的清单:
["key-a", "key-b", "key-c"]
我可以将列表分为两个级别:
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(prop("name")))
);
groupByTopThenZone(data);
但我不知道如何将它们组合起来以获得以下输出:
{
top1: {
"key-a": [
{
name: "junk-key-a-101",
top: "top1"
}
],
"key-b": [
{
name: "junk-key-b-102",
top: "top1"
}
]
},
top2: {
"key-c": [
{
name: "junk-key-c-103",
top: "top2"
},
{
name: "junk-key-c-104",
top: "top2"
}
]
}
}
我觉得我有点傻,我不能得到这个。有任何想法吗? Here是玩的地方
这不是使用 ramda,而是 vanilla JS。
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' } ];
const res = data.reduce((acc, val, ind, arr) => {
const top = val.top;
// if the top does not exist in the obj, create it
if (!acc[top]) {
acc[top] = {};
}
// get the key through split. you could also use a regex here
const keyFragments = val.name.split('-');
const key = [keyFragments[1], keyFragments[2]].join('-');
// if the key obj prop does not exist yet, create the array
if (!acc[top][key]) {
acc[top][key] = [];
}
// push the value
acc[top][key].push({ name: val.name, top: val.top });
return acc;
}, {});
console.log(res);
你们非常亲密。只需将这些函数与 compose
/pipe
结合起来就可以了。
(注意这里也是getZoneFromName
的简化版。)
const {pipe, groupBy, map, prop, slice} = R
//const getZoneFromName = n => join('-', slice(1, 3, split('-', n)));
const getZoneFromName = slice(5, -4)
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(pipe(prop("name"), getZoneFromName)))
)
const data = [{"name": "junk-key-a-101", "top": "top1"}, {"name": "junk-key-b-102", "top": "top1"}, {"name": "junk-key-c-103", "top": "top2"}, {"name": "junk-key-c-104", "top": "top2"}]
console.log(groupByTopThenZone(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
当然这个函数简化了那么多,内联它可能更容易:
const groupByTopThenZone = pipe(
groupBy(prop("top")),
map(groupBy(pipe(prop("name"), slice(5, -4)))
)
要记住的主要事情是 groupBy
不一定与 prop
绑定。我们可以对 any String
/Number
/Symbol
生成函数的结果进行分组。
另一种方法是构建每个最终对象并将它们全部合并:
你可以转换这个对象:
{
"top": "top1",
"name": "junk-key-a-101"
}
进入这个:
{
"top1": {
"key-a": [
{
"name": "junk-key-a-101",
"top": "top1"
}
]
}
}
具有这些功能:
const key = slice(5, -4);
const obj = ({top, name}) => ({
[top]: {
[key(name)]: [
{top, name}
]
}
});
现在您可以迭代数据,转换每个对象并将它们合并在一起:
const groupByTopTenZone = reduce(useWith(mergeDeepWith(concat), [identity, obj]), {});
完整示例:
const {slice, useWith, identity, reduce, mergeDeepWith, concat} = R;
const data = [
{ top: 'top1',
name: 'junk-key-a-101' },
{ top: 'top1',
name: 'junk-key-b-102' },
{ top: 'top2',
name: 'junk-key-c-103' },
{ top: 'top2',
name: 'junk-key-c-104' }
];
const key = slice(5, -4);
const obj = ({top, name}) => ({
[top]: {
[key(name)]: [
{top, name}
]
}
});
const groupByTopTenZone = reduce(useWith(mergeDeepWith(concat), [identity, obj]), {});
console.log(
groupByTopTenZone(data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>