gpt4 book ai didi

f# - 处理没有可变性的元组流?

转载 作者:行者123 更新时间:2023-12-02 05:36:59 27 4
gpt4 key购买 nike

所以我想要一个接收 Tuple 数组并返回相同类型但具有不同值的函数。

我想要做的是一个返回这种值的函数:

f( [1,10; 2,20; 3,40; 4,70] ) = [2,10; 3,20; 4,30]

所以如你所见,第一个数字基本不变(除了第一个项目没有被选中),但最后一个数字是当前数字与前一个数字的减法(20 - 10 = 10, 40 - 20 = 20, ...).

我试图在 F# 中提出一个不涉及可变性 的算法(对前一个值使用累加器意味着我需要一个可变变量),但我做不到弄清楚。这可能吗?

最佳答案

使用内置函数。在这种情况下,您可以使用 Seq.pairwise .该函数采用一系列输入并生成一系列包含先前值和当前值的对。一旦你有了对,你就可以使用 Seq.map将对转换为结果 - 在您的情况下,获取当前值的 ID 并从当前值中减去先前的值:

input 
|> Seq.pairwise
|> Seq.map (fun ((pid, pval), (nid, nval)) -> nid, nval-pval)

请注意,结果是一个序列 (IEnumerable<T>) 而不是一个列表 - 仅仅是因为 Seq模块包含更多(有用的)功能。您可以使用 List.ofSeq 将其转换回列表.

使用显式递归。如果您的任务不符合某些内置函数所涵盖的常见模式之一,那么答案就是使用递归(通常, 替换功能样式中的突变)。

为了完整起见,递归版本看起来像这样(这并不完美,因为它不是尾递归,所以它可能会导致堆栈溢出,但它演示了这个想法):

let rec f list = 
match list with
| (pid, pval)::(((nid, nval)::_) as tail) ->
(nid, nval-pval)::(f tail)
| _ -> []

这需要一个列表并查看列表的前两个元素 (pid, pval)(nid, nval) .然后它根据(nid, nval-pval)中的两个元素计算出新值。然后递归处理列表的其余部分(tail),跳过第一个元素。如果列表只有一个或更少的元素(第二种情况),则不返回任何内容。

可以使用“累加器”技巧编写尾递归版本。而不是写 newValue::(recursiveCall ...)我们将新产生的值累积在一个列表中作为参数保存,然后反转它:

let rec f list acc = 
match list with
| (pid, pval)::(((nid, nval)::_) as tail) ->
f tail ((nid, nval-pval)::acc)
| _ -> List.rev acc

现在您只需要使用 f input [] 调用该函数即可初始化累加器。

关于f# - 处理没有可变性的元组流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22543930/

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