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

使用Ramda实现带过滤项追踪功能的列表过滤

使用Ramda实现带剔除追踪的多规则过滤

现有如下数据列表,需要用Ramda应用多组过滤规则,同时追踪每个过滤器剔除的项ID:

const data = [
  {id: 1, name: "Andreas"},
  {id: 2, name: "Antonio"},
  {id: 3, name: "Bernhard"},
  {id: 4, name: "Carlos"}
];

常规多过滤可以用pipe(filter(predA), filter(predB), ...)(data)实现,但这里需要给每个过滤器绑定标识,记录它剔除的项。已经定义了filterBy函数,它会返回当前过滤器的剔除记录,以及过滤后剩余的数据:

const filterBy = (key, pred) => subs => {
  const [res, rej] = R.partition(pred, subs);
  return [{[key]: rej.map(R.prop('id'))}, res];
};

现在有两个过滤器:

const isEven = filterBy('id', i => i % 2 === 0);
const startsWithA = filterBy('name', R.startsWith('A'));

目标是得到包含所有剔除记录(按分组标识整理)和最终通过项的结果:

[
  {
    id: [1, 3],
    name: [3, 4]
  },
  [{id: 2, name: "Antonio"}]
]

解决方案

利用Ramda的reduce来组合这些过滤器,逐步累积剔除记录并传递过滤后的数据:

const combineFilters = (...filters) => data => {
  return filters.reduce(
    ([accRejections, currentData], filter) => {
      const [newRejection, filteredData] = filter(currentData);
      return [R.merge(accRejections, newRejection), filteredData];
    },
    [{}, data]
  );
};

// 调用组合后的过滤器
const result = combineFilters(isEven, startsWithA)(data);
console.log(result);

原理说明

  • reduce的初始值是[{}, data],空对象用来累积所有剔除记录,原始数据作为初始过滤输入。
  • 每一步执行过滤器,拿到当前过滤器的剔除记录和过滤后的数据。
  • 用R.merge将新的剔除记录合并到累积对象中,同时把过滤后的数据传给下一个过滤器。
  • 最终输出的数组第一个元素是所有分组的剔除ID列表,第二个元素是通过所有过滤的最终数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:26:14