我有一个生成一些元素并在List中返回它们的函数。该函数采用参数来过滤返回的元素。该函数如下所示:
let create x = [1..1000] |> List.filter (fun c -> (c % x) = 0)
现在我想用多个标准调用此函数,并将所有结果附加到单个列表中。
起初我在想这样做:
let result = (create 100)
|> List.append (create 300)
|> List.append (create 500)
|> List.append (create 3)
printf "%A" result
但我没有用List.append
表达式找到优雅且重复的解决方案。
我尝试了第二种解决方案:
let result = [100; 300; 500; 3] |> List.map (fun c -> create c)
|> List.reduce (fun acc c -> acc |> List.append c)
printf "%A" result
这个解决方案更简洁,但有些东西我不喜欢它。我发现它不太清楚,更难以猜测我们试图实现的目标。
所以,我正在寻找第三种解决方案,并试图用计算表达式实现一个新的解决方案:
type AppendBuilder() =
member this.Bind (x, f) = f x |> List.append x
member this.Return x = x
然后像这样使用它:
let append = new AppendBuilder()
let result = append {
let! a = create 100
let! b = create 300
let! c = create 500
let! d = create 3
return []
}
printf "%A" result
这最后一个解决方案有效,我更喜欢它。我发现它更清晰,更容易理解我们正在做什么,没有重复的List.append表达式。但仍有一些问题。我不喜欢return []
部分,这似乎不自然且不清楚。但是这个技巧对于它的运作是必要的。
第三种解决方案是我的最爱,但我不确定这是解决问题的正确方法。它解决了问题,我得到了正确的结果,但我不确定这是否是正确的方法。
我可以保留第三种解决方案而不会对我的意图造成混淆吗?解决方案是否足够清晰以保持原样?我正在寻找一个更专注于操作的解决方案(此处调用create x
),而不会重复表达代码寄存器(此处调用List.append
)。
答案 0 :(得分:7)
因为要求作为答案:
最简单的方法是使用List.collect
来完成地图,并在一个步骤中组合列表。
这种情况下的解决方案看起来像
[100;300;500;3] |> List.collect create
答案 1 :(得分:5)
let result =
[
yield! [ 100 .. 100 .. 1001]
yield! [ 300 .. 300 .. 1001]
yield! [ 500 .. 500 .. 1001]
yield! [ 3 .. 3 .. 1001]
]
值得注意的是:使用Python列表后,我发现它们更友好,因为您可以使用值1000
而不是值1001
来表示F#。
如果您的create
函数始终为step function
,那么使用List的内置功能会更有意义。如果您打算使用无法使用List的内置功能的create
函数,那么John Palmer的评论会更有意义。
let result =
[100;300;500;3]
|> List.collect create
Anton Schwaighofer在评论中建议的变体形式是允许create
函数的值作为参数出现。
let makeList parms =
parms
|> List.collect create
然后用作
let result = makeList [100;300;500;3]
let makeList = List.collect create
答案 2 :(得分:2)
如果第3个版本是你最喜欢的版本,那么你可能想要使用列表理解:
let result =
[ yield! create 100
yield! create 300
yield! create 500
yield! create 3 ]
答案 3 :(得分:1)
您可以从seq
计算的懒惰中受益:
seq {
yield! create 100
yield! create 300
yield! create 500
yield! create 3
} |> List.ofSeq
然后使用List.ofSeq