我是 Ramda 的新手,我正在努力实现以下目标:
我有一个对象数组(即消息)。
我想按照对方ID(发件人或收件人ID,不论是哪一个,请参阅下面的groupBy
lambda)对邮件进行分组。
我将获得一个对象,其密钥将是对方的ID,并且值是与该对方交换的消息的数组。
然后我希望按日期排序这些消息数组。
最后保留最新消息,从而获得一个包含与每个对方交换的最新消息的数组。
因为我上面有两个对方,所以我应该有两个消息的数组。
以下是我的尝试:
const rawMessages = [
{
"sender": {
"id": 1,
"firstName": "JuliettP"
},
"recipient": {
"id": 2,
"firstName": "Julien"
},
"sendDate": "2017-01-28T19:21:15.863",
"messageRead": true,
"text": "ssssssss"
},
{
"sender": {
"id": 3,
"firstName": "Juliani"
},
"recipient": {
"id": 1,
"firstName": "JuliettP"
},
"sendDate": "2017-02-01T18:08:12.894",
"messageRead": true,
"text": "sss"
},
{
"sender": {
"id": 2,
"firstName": "Julien"
},
"recipient": {
"id": 1,
"firstName": "JuliettP"
},
"sendDate": "2017-02-07T22:19:51.649",
"messageRead": true,
"text": "I love redux!!"
},
{
"sender": {
"id": 1,
"firstName": "JuliettP"
},
"recipient": {
"id": 3,
"firstName": "Juliani"
},
"sendDate": "2017-03-13T20:57:52.253",
"messageRead": false,
"text": "hello Juliani"
},
{
"sender": {
"id": 1,
"firstName": "JuliettP"
},
"recipient": {
"id": 3,
"firstName": "Juliani"
},
"sendDate": "2017-03-13T20:56:52.253",
"messageRead": false,
"text": "hello Julianito"
}
];
const currentUserId = 1;
const groupBy = (m: Message) => m.sender.id !== currentUserId ? m.sender.id : m.recipient.id;
const byDate = R.descend(R.prop('sendDate'));
const sort = (value, key) => R.sort(byDate, value);
const composition = R.compose(R.map, R.head, sort, R.groupBy(groupBy));
const latestByCounterParty = composition(rawMessages);
console.log(latestByCounterParty);
这是相应的codepen:
https://codepen.io/balteo/pen/JWOWRb
有人可以帮忙吗?
修改:以下是未公开版本的链接:here。没有currying,行为是相同的。请参阅下面的评论,我的问题是关于currying的必要性。
答案 0 :(得分:2)
你的例子接近你想要的,尽管你只需要将head
和sort
的组合移动到给予map
的函数参数然后调用{{1在最终结果上将对象转换为值数组。
values
答案 1 :(得分:2)
虽然我认为solution from Scott Christopher很好,但我自己可以采取两个步骤。
注意到important rules地图之一就是那个
map(compose(f, g)) ≍ compose(map(f), map(g))
当我们已经进入合成管道时,我们可以选择取消此步骤:
R.map(R.compose(R.head, R.sort(R.descend(R.prop('sendDate'))))),
并将整体解决方案变为
const currentMessagesForId = R.curry((id, msgs) =>
R.compose(
R.values,
R.map(R.head),
R.map(R.sort(R.descend(R.prop('sendDate')))),
R.groupBy(m => m.sender.id !== id ? m.sender.id : m.recipient.id)
)(msgs)
)
这样做,当然是品味问题。但我发现它更清洁。下一步也是品味问题。我选择将compose
用于可以在一行中列出的内容,从而在格式compose(f, g, h)(x)
和f(g(h(x)))
之间建立明显的联系。如果它跨越多行,我更喜欢使用pipe
,它的行为方式相同,但从头到尾运行它的函数。所以我会进一步改变它看起来像这样:
const currentMessagesForId = R.curry((id, msgs) =>
R.pipe(
R.groupBy(m => m.sender.id !== id ? m.sender.id : m.recipient.id),
R.map(R.sort(R.descend(R.prop('sendDate')))),
R.map(R.head),
R.values
)(msgs)
)
我发现这种自上而下的阅读比较长的compose
版本所需的自下而上更容易。
但是,正如我所说,这些都是品味问题。
您可以在 Ramda REPL 。
上看到这些示例