Ramda 组然后将兄弟姐妹转换为 children
Ramda group then convert siblings to children
在 ramda.js 中,我如何按字段对列表进行分组和排序,然后将每个组中除第一项以外的所有项都移动到该项的 children 中?
例如,在我按名称分组并按日期降序排序的下方:
[{ id: 1, name: 'bob', date: '2007-03-05', count: 15},
{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3},
{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
进入
[{ id: 1, name: 'bob', date: '2007-03-05', count: 15,
children: [{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27}]
},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3,
children: [{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
}
]
我知道我可以使用 R.head 获取整个列表的顶部项目,使用 R.tail 获取其余项目,然后将其添加为 child 使用 R.merge, 但我不知道如何只抓取列表中组的顶部或尾部。
您还没有对它们进行分组,只是按名称排序。要将它们分组到数组数组中,请使用 R.groupWith
:
R.groupWith(R.eqProps("name"))
将其应用于您的数据后,使用 map
从每个组创建一个对象。
这是您获得理想结果的一种方法
const groupByName = groupBy(obj => obj.name);
const sortByDate = sortBy(obj => obj.date);
const grouped = pipe(groupByName, map(sortByDate), values);
reduce( (acc, val) => {
acc.push(merge(head(val), {children: tail(val)}));
return acc;
}, [], grouped(data));
可能有更好的方法,但我认为这是一个开始:
function yourAnswer (data) {
const groupByName = groupBy((person) => person.name)
return (
Object.values(groupByName(data))
.map((g) => g.sort((a, b) => a.id - b.id)) // sort by ascending id
.map(function(g) { // for each group, sorted by id
const o = Object.assign(g[0]) // create an object from the minimal id
o['children'] = g.slice(1) // assign 'children' to be equal the other objects in the group
return o
})
)}
let data = [{ id: 1, name: 'bob', date: '2007-03-05', count: 15},
{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3},
{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
console.log(yourAnswer(data))
在 ramda repl 试试。
另一种方法:
const fn = pipe(
groupBy(prop('name')),
values,
map(lift(assoc('children'))(tail, head))
);
如果你想在里面加上排序,你可以在values,
之后加上这个:
map(sort(descend(prop('date')))),
如果这不清楚:map(lift(assoc('children'))(tail, head))
您可以将其替换为等效的:
map((group) => assoc('children', tail(group), head(group)))
您可以在 Ramda REPL.
上看到实际效果
在 ramda.js 中,我如何按字段对列表进行分组和排序,然后将每个组中除第一项以外的所有项都移动到该项的 children 中?
例如,在我按名称分组并按日期降序排序的下方:
[{ id: 1, name: 'bob', date: '2007-03-05', count: 15},
{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3},
{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
进入
[{ id: 1, name: 'bob', date: '2007-03-05', count: 15,
children: [{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27}]
},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3,
children: [{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
}
]
我知道我可以使用 R.head 获取整个列表的顶部项目,使用 R.tail 获取其余项目,然后将其添加为 child 使用 R.merge, 但我不知道如何只抓取列表中组的顶部或尾部。
您还没有对它们进行分组,只是按名称排序。要将它们分组到数组数组中,请使用 R.groupWith
:
R.groupWith(R.eqProps("name"))
将其应用于您的数据后,使用 map
从每个组创建一个对象。
这是您获得理想结果的一种方法
const groupByName = groupBy(obj => obj.name);
const sortByDate = sortBy(obj => obj.date);
const grouped = pipe(groupByName, map(sortByDate), values);
reduce( (acc, val) => {
acc.push(merge(head(val), {children: tail(val)}));
return acc;
}, [], grouped(data));
可能有更好的方法,但我认为这是一个开始:
function yourAnswer (data) {
const groupByName = groupBy((person) => person.name)
return (
Object.values(groupByName(data))
.map((g) => g.sort((a, b) => a.id - b.id)) // sort by ascending id
.map(function(g) { // for each group, sorted by id
const o = Object.assign(g[0]) // create an object from the minimal id
o['children'] = g.slice(1) // assign 'children' to be equal the other objects in the group
return o
})
)}
let data = [{ id: 1, name: 'bob', date: '2007-03-05', count: 15},
{ id: 2, name: 'bob', date: '2007-03-04', count: 32},
{ id: 3, name: 'bob', date: '2007-03-01', count: 27},
{ id: 4, name: 'jack', date: '2007-03-04', count: 3},
{ id: 5, name: 'jack', date: '2007-02-22', count: 5}]
console.log(yourAnswer(data))
在 ramda repl 试试。
另一种方法:
const fn = pipe(
groupBy(prop('name')),
values,
map(lift(assoc('children'))(tail, head))
);
如果你想在里面加上排序,你可以在values,
之后加上这个:
map(sort(descend(prop('date')))),
如果这不清楚:map(lift(assoc('children'))(tail, head))
您可以将其替换为等效的:
map((group) => assoc('children', tail(group), head(group)))
您可以在 Ramda REPL.
上看到实际效果