簡體   English   中英

從 Python 轉換為 F# 遞歸函數?

[英]Converting from Python to F# recursive function?

我正在嘗試將此 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)

我已經開始:

let findMatches s l =
    for e1, e2 in list do
        if e1 = s then ...

如果我朝着正確的方向前進或下一步要去哪里,則並非完全如此。

在 Python 中,在執行過程中改變(“更改”、“更新”)數據是一種常見的做法 - 就像您正在處理temp列表一樣,在每一步都改變它。 盡管即使在 Python 中它也普遍不受歡迎,但語言本身使它非常容易,因此非常誘人。

在 F# 中,仍然可以改變數據,但語言使它變得困難。 故意。 好了,沒有那么難-它只是一些額外的字符, -但至少變異的數據是不是默認。 這通常是一種更好的方法,甚至 Python 社區現在也承認這一點。

相反,F# 方式(以及一般來說,功能方式)不是改變數據,而是通過轉換舊數據來創建新數據。 就像函數的作用一樣(“函數”我的意思是“數學函數”)。

特別是,您的 Python 循環似乎在做的是 (1) 通過i[0]過濾輸入列表,然后 (2) 通過丟棄i[0]並只留下i[1]轉換(通常稱為“映射”)每個元素i[1] ,然后(3)排序。 這可以用 F# 寫成這樣:

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

該程序不是通過重復變異來“構建”列表,而是通過三次轉換輸入列表來創建結果列表:過濾,然后映射,然后排序。 另一個需要注意的是,轉換本身是由較小的部分構建的:整個列表的轉換是通過轉換單個元素的轉換來實現的。

對於像這樣的簡單情況(排序除外),F# 還提供了特殊的語法——所謂的“列表推導式”。 它是語法糖,它在幕后執行與上述類似的轉換,但語法(可以說)更具可讀性:

let findMatches s l =
    [ for e1, e2 in l do
        if e1 == s then yield e2
    ]
    |> List.sort

請注意,盡管這看起來與您的 Python 程序幾乎相同,但含義卻略有不同。 這個程序不是“做這個,然后做那個”(又名“命令式”),這個程序說“結果以這種方式取決於輸入”(又名“功能式”)。

我能想到的從 Python 示例代碼到 F# 的最直接映射:

// I tend to specify the signatures of methods as I find it helpful
let findMatches (s : 'K) (l : seq<'K*'V>): seq<'V> =
  // ResizeArray is an alias for System.Collections.Generic.List<_>
  let temp = ResizeArray ()
  for e1, e2 in l do
    if e1 = s then
      temp.Add e2
  temp.Sort ()
  // F# don't do implicit upcasts like C# so an explicit upcast from
  //  ResizeArray to seq
  upcast temp

正如 Fyodor 在 F# 中提到的,習慣用法(即常用方法)是為了避免可變性,並且更喜歡內置的高階函數(如過濾器和映射)來處理列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM