2 回答

TA貢獻1785條經驗 獲得超8個贊
在Python中,在進行過程中改變(“更改”,“更新”)數據是一種常見的做法 - 就像你對列表所做的那樣,在每一步都改變它。雖然即使在Python中也普遍不贊成它,但該語言本身使它變得非常容易,因此非常誘人。temp
在 F# 中,仍然可以更改數據,但語言使它變得困難。故意。好吧,這并不難 - 這只是幾個額外的字符,但至少突變數據不是默認的。這是一種通常更好的方法,甚至Python社區現在也認識到了這一點。
相反,F# 方式(以及一般的函數方式)不是改變數據,而是通過轉換舊數據來創建新數據。例如,函數的作用(其中“函數”是指“數學函數”)。
特別是,你的Python循環似乎正在做的是(1)過濾輸入列表,然后(2)通過丟棄并只留下來轉換(通常稱為“映射”)每個元素,然后(3)排序。這可以用 F# 編寫,如下所示:i[0]i[0]i[1]
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程序幾乎相同,但含義卻略有不同。而不是“做這個,然后做那個”(又名“命令式風格”),這個程序說“結果取決于以這種方式輸入”(又名“功能風格”)。

TA貢獻1804條經驗 獲得超3個贊
我能想到的從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# 中提到的,這個成語(即常用方法)是避免可變性,并且更喜歡內置的高階函數(如過濾器和 map)來處理列表。
添加回答
舉報