gpt4 book ai didi

f# - 如何改进这个 F# 功能

转载 作者:行者123 更新时间:2023-12-02 17:43:44 25 4
gpt4 key购买 nike

我在 C# 方面经验丰富,但对 F# 和函数式编程很陌生。现在我正在尝试在 F# 中实现一个类库。这是其中一项功能:它采用 <=9 的整数列表,并将连续的 9(如 9,9,9,9)更改为 9,10,11,12。例如 [9;9;9;1;4;0;1;9;9 ;9;9] 将更改为 [9; 10; 11; 1; 4; 0; 1; 9; 10; 11; 12]。

C# 函数很简单:

void ReleaseCap(List<int> items)
{
for (int i = 1; i < items.Count; i++)
{
var current = items[i];
var previous = items[i - 1];
//If curernt value = 9 and previous >=9, then current value should be previous+1
if (current == 9 && previous >= 9)
{
items[i] = previous + 1;
}
}
}

现在是我的 F# 尾递归。它不是按索引循环列表,而是递归地将项目从初始列表移动到已处理列表,直到初始列表中的所有内容都消失:

let releaseCap items =
let rec loop processed remaining = //tail recursion
match remaining with
| [] -> processed //if nothing left, the job is done.
| current :: rest when current = 9 -> //if current item =9
match processed with
// previous value >= 9, then append previous+1 to the processed list
| previous :: _ when previous >= 9 -> loop (previous+1 :: processed) rest
//if previous < 9, the current one should be just 9
| _ -> loop (current :: processed) rest
//otherwise, just put the current value to the processed list
| current :: rest -> loop (current :: processed) rest
loop [] items |> List.rev

虽然 C# 版本简单且直观,但 F# 代码却冗长且不直观。 F#代码是否有任何部分可以改进,使其更加优雅?

最佳答案

您可以重用现有函数以简化代码。通常,当您更改列表中的项目时,您会想到map,但在这种情况下,您需要从之前的计算中记住一些东西,这些内容应该为每个项目传递,因此您应该致力于折叠相关功能。

这是一个:List.scan

let releaseCap items =
items
|> List.scan (fun previous current ->
if current = 9 && previous >= 9 then previous + 1
else current) 0
|> List.tail

FP 不仅仅是使用递归代替循环。递归通常用于基本和可重用的函数,然后通过组合这些函数可以解决复杂的问题。

注意:您正在将 C# 解决方案与 F# 解决方案进行比较,但是您是否注意到,除了语言之外,这两种解决方案之间还有重要的区别?您的 C# 解决方案使用可变性。

关于f# - 如何改进这个 F# 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32831902/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com