[英]Recursive variable definitions in Python and F# (probably OCaml, too)
[英]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.