You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Ramda的pipe实现嵌套数组的过滤与排序?

如何用Ramda的pipe实现过滤与排序功能?

需求场景

需要处理如下数组:

const items = [
  { id: 1, subitems: [{name: 'Foo', price: 1000}]},
  { id: 2, subitems: [{name: 'Bar'}]},
  { id: 3, subitems: [{name: 'Foo', price: 500}]},
  { id: 4, subitems: [{name: 'Qux'}]},
]

要实现两个操作:

  1. 过滤出subitems中包含name为Foo的元素的项
  2. 按Foo的price进行排序(原始代码逻辑为降序,若需升序可调整)

原始JS实现如下:

const findFoo = value => value.name === 'Foo'

items
  .filter(item => item.subitems.find(findFoo))
  .sort((a, b) => a.subitems.find(findFoo).price > b.subitems.find(findFoo).price ? -1 : 1)

// 原始注释预期结果:[{ id: 3, subitems: [...] }, { id: 1, subitems: [...] }]

问题分析

你尝试的Ramda代码返回空数组,核心问题是compose的执行顺序搞反了:

R.pipe(
  R.filter(
    R.compose(
      R.path(['subitems']),
      R.propEq('name', 'Foo')
    )
  ),
  // Todo: sorting...
)(items)

compose是从右到左执行的,这段代码会先对整个item执行R.propEq('name', 'Foo')(判断item自身的name是否为Foo,显然所有item都不满足,返回false),再对false执行R.path(['subitems'])得到undefined,最终过滤条件全为false,所以返回空数组。

正确实现

1. 修正过滤逻辑

需要先取item的subitems,再判断其中是否存在name为Foo的元素,用R.any替代find(find返回匹配项,存在即为truthy;any直接返回布尔值,逻辑等价):

R.filter(R.compose(R.any(R.propEq('name', 'Foo')), R.prop('subitems')))

2. 实现排序逻辑

用R.sort结合R.descend(生成降序比较器),先取出每个item中Foo的price,再按该值降序排列:

R.sort(R.descend(R.compose(R.prop('price'), R.find(R.propEq('name', 'Foo')), R.prop('subitems'))))

完整pipe代码

const result = R.pipe(
  // 过滤出包含Foo的项
  R.filter(R.compose(R.any(R.propEq('name', 'Foo')), R.prop('subitems'))),
  // 按Foo的price降序排列
  R.sort(R.descend(R.compose(R.prop('price'), R.find(R.propEq('name', 'Foo')), R.prop('subitems'))))
)(items)

console.log(result)
// 输出:[{ id: 1, subitems: [{name: 'Foo', price: 1000}] }, { id: 3, subitems: [{name: 'Foo', price: 500}] }]

如果想要得到你注释中的升序结果(id3在前,id1在后),只需把R.descend换成R.ascend即可:

const resultAsc = R.pipe(
  R.filter(R.compose(R.any(R.propEq('name', 'Foo')), R.prop('subitems'))),
  R.sort(R.ascend(R.compose(R.prop('price'), R.find(R.propEq('name', 'Foo')), R.prop('subitems'))))
)(items)

console.log(resultAsc)
// 输出:[{ id: 3, subitems: [{name: 'Foo', price: 500}] }, { id: 1, subitems: [{name: 'Foo', price: 1000}] }]

补充说明

  • R.compose:函数组合,从右到左执行,适合把多个单参数函数串联起来
  • R.any:判断数组中是否有至少一个元素满足条件,等价于原生Array.some
  • R.find:返回数组中第一个满足条件的元素,等价于原生Array.find
  • R.descend/R.ascend:生成排序比较器,分别对应降序和升序,简化排序逻辑

内容的提问来源于stack exchange,提问作者fnx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:25:48