带过滤功能的 F# List.mapi 函数

Kot*_*ote 5 f# list filter

我有这样一行代码:

list |> List.mapi (fun i x -> y, i)
Run Code Online (Sandbox Code Playgroud)

(假设 y 是已经定义的类型)

但我想返回具有某些条件的元素(例如过滤它)

我不能这样写:

 list |> List.mapi (fun i x -> if 'condition' then y, i)
Run Code Online (Sandbox Code Playgroud)

因为它也需要其他条件,而我没有“其他”情况。我也没有设法同时使用过滤器,因为我还需要返回正确的索引,如果我过滤列表,索引将被更改。有任何想法吗?

编辑 到现在为止,我是这样实现的:

list |> List.mapi (fun i a -> if (a = None) then O, i else X, i) |> List.filter (fun (a,i) -> a = O)
Run Code Online (Sandbox Code Playgroud)

对于其他情况,我给出了无用的 X,我只是为了能够在此之后写入条件并删除 X 条件。它起作用了,这就是我想要的结果。但我相信有更好的解决方案。

Car*_*Dev 5

让我再补充一个答案:根据您的问题和评论,我了解到您希望根据值按条件过滤列表,同时保留原始索引。我不确定结果是否应该由固定值列表和原始索引组成,或者您想要映射。以下允许两者:

let indexedFilterMap p f =
    List.indexed
    >> List.filter (snd >> p)
    >> List.map (fun (i, x) -> f x, i)
Run Code Online (Sandbox Code Playgroud)
  1. 添加索引
  2. 使用索引列表的第二个值按 p 过滤,即原始值
  3. 映射剩余的值并反转元组中的顺序(st it is value, index)

如果您需要映射的索引(因为问题标题包括mapi):

let indexedFilterMapi p f =
    List.indexed
    >> List.filter (snd >> p)
    >> List.map f
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要过滤器的索引:

let indexedFilteriMap p f =
    List.indexed
    >> List.filter p
    >> List.map (fun (i, x) -> f x, i)
Run Code Online (Sandbox Code Playgroud)

组合应该很简单。

然后可以使用这些:

let list = ['a'; 'b'; 'c']
let condition = (<>) 'b'
let y = "fixed value"

indexedFilterMap condition (fun _ -> y) list // [("fixed value", 0); ("fixed value", 2)]

let m (i, _) = sprintf "fixed value %i" i
indexedFilterMapi condition m list // ["fixed value 0"; "fixed value 2"]

let c (i, _) = i <> 1
indexedFilteriMap c (fun _ -> y) list // [("fixed value", 0); ("fixed value", 2)]
Run Code Online (Sandbox Code Playgroud)