【问题标题】:Item filtering but keeping track of filtered out items项目过滤,但跟踪过滤掉的项目
【发布时间】:2022-11-02 07:22:15
【问题描述】:

假设我有一个像下面这样的项目列表,我想用 ramda 将过滤器列表应用到它上面。

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

没什么大不了的:管道(过滤器(predA),过滤器(predB),...)(数据)

棘手的部分是我想用一个键定义我的过滤器,以跟踪哪些项目已被哪个过滤器过滤掉。

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

这一切都在尖叫单子链或传感器,但我无法理解如何将它们组合在一起。

假设我有 2 个谓词:

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

我想得到一个看起来像这个元组的结果,带有一个拒绝图和一个“接受”项目列表(isEven 抛出 1 和 3,startsWithA 拒绝 3 和 4):

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

【问题讨论】:

    标签: ramda.js


    【解决方案1】:

    香草JS版

    我对使用字段名称来描述谓词感到困扰。如果我们也有 const nameTooLong = ({name}) => name .length < 8 会发生什么。那么我们如何区分输出中的两个谓词呢?所以我更喜欢使用描述性的谓词名称,例如,

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

    这就是我在这段代码中所做的:

    const process = (preds) => (xs) => {
      const rej = Object .fromEntries (Object .entries (preds) 
        .map (([k, v]) => [k, xs .filter (x => !v (x)) .map (x => x .id)])
      )
      const excluded = Object .values (rej) .flat()
      return [rej, data .filter (({id}) => !excluded .includes (id))]
    }
    
    const data = [{id: 1, name: "Andreas"}, {id: 2, name: "Antonio"}, {id: 3, name: "Bernhard"}, {id: 4, name: "Carlos"}]
    
    console .log (process ({
      isEven: ({id}) => id % 2 === 0, 
      startsWithA: ({name}) => name .startsWith ('A')
    }) (data))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    更改它以返回类似于您请求的格式的内容并不会太难。

    使用 Ramda

    这个问题被标记为Ramda,我最初使用 Ramda 工具编写了这个问题,其版本如下所示:

    const process = (preds) => (xs) => {
      const rej = pipe (map (flip (reject) (xs)), map (pluck ('id'))) (preds)
      const excluded = uniq (flatten (values (rej)))
      return [rej, reject (pipe (prop ('id'), flip (includes) (excluded))) (data)]
    }
    

    我们可以继续解决这个问题,直到我们完全没有意义为止。我只是看不出有任何理由。

    我是 Ramda 的创始人和忠实粉丝,但我不认为它比香草版本更具可读性。有一个例外:Ramda 的 map 在普通对象上工作比在香草代码中的 Object .entries -> map -> Object .fromEntries 舞蹈要好得多。不过,我可能会使用该功能并将其余部分留在香草中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 2021-07-09
      • 2021-02-23
      • 2020-08-29
      • 1970-01-01
      相关资源
      最近更新 更多