【问题标题】:fp-ts: Filter array based on next elementfp-ts:根据下一个元素过滤数组
【发布时间】:2020-05-03 21:10:26
【问题描述】:

我从函数式编程开始/fp-ts。 我正在尝试编写一个函数,如果 next 元素的条件得到满足,它会保留一个元素。

例子:

const condition = (i: number) => i % 10 === 0;
filterNext(condition, [19, 20, 3, 18, 8, 48, 20, 4, 10]) // => [3, 4]

我可能还需要扩展它,以便 匹配和下一个元素都包含在内,如:

const condition = (i: number) => i % 10 === 0;
filterNext(condition, [19, 20, 3, 18, 8, 48, 90, 4, 10]) // => [10, 3, 90, 4, 10]

我不知道如何为两者中的任何一个构建适当的纯函数。

欢迎任何提示。

【问题讨论】:

  • 如果您需要前瞻语义,通常必须求助于递归。也许有一个花哨的递归方案(折叠),但我不知道。

标签: functional-programming fp-ts


【解决方案1】:

首先,让我给你看一下代码:

import * as O from "fp-ts/lib/Option";
import * as A from "fp-ts/lib/Array";
import { pipe } from "fp-ts/lib/pipeable";

const filterOnPrevious = <T>(condition: (T) => boolean, xs: T[]): T[] =>
  pipe(
    A.tail(xs),
    O.getOrElse<T[]>(() => []),
    tail => A.zip(tail, xs),
    A.filter(([_, x]) => condition(x)),
    A.map(([x]) => x)
  );

其次,您编写“如果满足 next 元素上的条件”,但您的示例显示该条件应该传递给 previous 元素。该代码适用于您的示例。

该任务分为三个部分:

  1. 为过滤器准备数据
  2. 过滤器
  3. 提取您需要的内容

神奇的函数是Array.zip,它从两个数组创建对。

我使用原始数组和移位(删除第一个元素)数组运行它。这将创建对,其中第一个值是原始值,第二个值是运行条件的值。

因为Array.tail 返回一个选项(如果数组为空则返回none),我们需要先通过Option.getOrElse 运行它。

在最后一步中,在过滤了对之后,我通过它们进行映射并从每对中获取原始值。

虽然我使用一对,但您可以使用对象或其他结构。我喜欢对,因为它们易于键入和使用,这要归功于数组解构。

如何改变行为:

  • filterOnNext:将A.zip(tail, xs) 切换为A.zip(xs, tail)。同样,第一个值是原始值,第二个是应该运行条件的值。或者,更新 A.filterA.map,使其使用该对中的另一个值。
  • 同时保留:这很棘手,因为如果连续三个数字满足条件尚不清楚期望的结果是什么。无论如何,如果条件传递到第二个值,我仍然建议首先创建一个值作为结果的对。

【讨论】:

    【解决方案2】:

    让我知道这是否有效

    import {Predicate, Refinement} from 'fp-ts/lib/function'
    import {filterWithIndex} from 'fp-ts/lib/Array'
    function filterWithNext<A>(predicate: Predicate<A>, xs: Array<A>): Array<A>
    function filterWithNext<A, B extends A>(
      predicate: Refinement<A, B>,
      xs: Array<A>
    ): Array<B> {
      return filterWithIndex<A, B>(
        (i, x): x is B => predicate(x) && i !== xs.length && predicate(xs[i + 1])
      )(xs)
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-20
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多