从 Python 转换为 F# 递归函数?

use*_*037 0 python f# f#-interactive

我正在尝试将此 Python 代码转换为 F# 而不使用不可变变量或List.map. 我仍然是这个新手。

def findMatches(s,l):
    temp=[]
    for i in l:
        if i[0]==s:
            temp.append(i[1])
    temp.sort()
    return temp

l=findMatches("A",[("A",5),("AA",9),("BB",6),("A",0)])
print(l)
Run Code Online (Sandbox Code Playgroud)

我已经开始:

let findMatches s l =
    for e1, e2 in list do
        if e1 = s then ...
Run Code Online (Sandbox Code Playgroud)

如果我朝着正确的方向前进或下一步要去哪里,则并非完全如此。

Fyo*_*kin 5

在 Python 中,在执行过程中改变(“更改”、“更新”)数据是一种常见的做法 - 就像您正在处理temp列表一样,在每一步都改变它。尽管即使在 Python 中它也普遍不受欢迎,但语言本身使它非常容易,因此非常诱人。

在 F# 中,仍然可以改变数据,但语言使它变得困难。故意。好了,不难-它只是一些额外的字符, -但至少变异的数据是不是默认。这通常是一种更好的方法,甚至 Python 社区现在也承认这一点。

相反,F# 方式(以及一般来说,功能方式)不是改变数据,而是通过转换旧数据来创建新数据。就像函数的作用一样(“函数”我的意思是“数学函数”)。

特别是,您的 Python 循环似乎在做的是 (1)过滤输入列表i[0],然后 (2) 通过丢弃i[0]和只留下来转换(通常称为“映射”)每个元素i[1],然后 (3) 排序。这可以用 F# 写成这样:

let findMatches s l =
    l
    |> List.filter (fun (e1, _) -> e1 == s)  // filtering
    |> List.map (fun (_, e2) -> e2)          // mapping
    |> List.sort
Run Code Online (Sandbox Code Playgroud)

该程序不是通过重复变异来“构建”列表,而是通过三次转换输入列表来创建结果列表:过滤,然后映射,然后排序。另一个需要注意的是,转换本身是由较小的部分构建的:整个列表的转换是通过转换单个元素的转换来实现的。

对于像这样的简单情况(排序除外),F# 还提供了特殊的语法——所谓的“列表推导式”。它是语法糖,它在幕后执行与上述类似的转换,但语法(可以说)更具可读性:

let findMatches s l =
    [ for e1, e2 in l do
        if e1 == s then yield e2
    ]
    |> List.sort
Run Code Online (Sandbox Code Playgroud)

请注意,尽管这看起来与您的 Python 程序几乎相同,但含义却略有不同。这个程序不是“做这个,然后做那个”(又名“命令式”),这个程序说“结果以这种方式取决于输入”(又名“功能式”)。