假設兩個長度相同的排序串列,鍵值串列let k = [1;1;2;2;3;3]和數字串列let n = [1;2;3;4;5;6]。兩個串列上的第 i 個位置相互映射,這意味著該元素n=1的鍵值為k=1,n=2鍵值為k=1... 等等。
如何在 F# 中創建一個映射具有相同鍵值的多個元素的串列?
因此輸出將采用格式[[n1;n2;key];[n1;n2;key]...],示例輸出為[[1;2;1];[3;4;2];[5;6;3]].
uj5u.com熱心網友回復:
這可以通過將兩個串列“壓縮”在一起然后按密鑰分組來實作:
let groupByKey keys numbers =
List.zip keys numbers
|> List.groupBy fst
|> List.map (fun (key, values) -> key, (values |> List.map snd))
groupByKey k n // [(1, [1; 2]); (2, [3; 4]); (3, [5; 6])]
上面版本的函式沒有您指定的確切輸出格式,但它是一個更加結構化的輸出,其中串列中的每個專案都是鍵的元組和該鍵的值串列。這可能是更清晰的代碼的首選,具體取決于您將如何處理結果。
要獲得您指定的格式,可以稍作更改:
let groupByKey keys numbers =
List.zip keys numbers
|> List.groupBy fst
|> List.map (fun (key, values) -> [
yield! values |> List.map snd
yield key
])
groupByKey k n // [[1; 2; 1]; [3; 4; 2]; [5; 6; 3]]
uj5u.com熱心網友回復:
我認為您正在尋找的是Seq.zip,它需要兩個序列(串列是序列)并回傳一個對序列。
另請注意,您使用逗號指定了串列,但 F# 使用分號來分隔串列元素。
let keys = [ 1; 1; 2; 2; 3; 3 ]
let values = [ 1; 2; 3; 4; 5; 6 ]
let map =
values
|> Seq.zip keys
|> Seq.groupBy (fun (k, v) -> k)
|> Seq.map (fun (k, vs) -> k, vs |> Seq.map snd |> Seq.toList)
|> Map.ofSeq
printfn "%A" map
// map [(1, [1; 2]); (2, [3; 4]); (3, [5; 6])]
要獲得您正在尋找的格式(盡管我認為您應該考慮 a Map),您可以像這樣解壓縮它:
let mapList =
map
|> Map.toSeq
|> Seq.map (fun (k, vs) -> vs @ [ k ])
|> Seq.toList
printfn "%A" mapList
// [[1; 2; 1]; [3; 4; 2]; [5; 6; 3]]
uj5u.com熱心網友回復:
你所描述的是一個地圖資料結構,所以我會使用一個,而不是用一堆串列函式自己實作它,你可以以這樣的方式轉換你的兩個串列
let k = [1;1;2;2;3;3]
let n = [1;2;3;4;5;6]
let mapKeyToValues keys values =
let folder m k v =
m |> Map.change k (function
| Some old -> Some (v :: old)
| None -> Some [v]
)
List.fold2 folder Map.empty keys values
現在與
let r = mapKeyToValues k n
你得到一個像
Map [
1, [2; 1]
2, [4; 3]
3, [6; 5]
]
這相當于 JSON-Object
{
"1": [2,1],
"2": [4,3],
"3": [6,5]
}
通常你可以寫
let r = Map (List.zip k n)
這樣,(k,v)您可以從元組中創建這樣的地圖資料結構。但是一個新的密鑰,只是覆寫了一個舊的,所以你得到
Map [
(1, 2)
(2, 4)
(3, 6)
]
這就是您需要Map.change. 您遍歷每個(key,value)串列,List.fold2然后將其添加到地圖資料結構中。如果鍵不存在(這種None情況),您將創建一個串列作為具有唯一值的值。如果Some已經添加了一個鍵,并且您將您的值添加到已經存在的串列中。
在這個例子中,我認為值的順序無關緊要。如果您希望它們出現在值串列中的順序相同,則必須使用List.foldBack2代替List.fold2。但是你必須改變一些引數的順序。這對你來說應該是一個練習,以便更好地理解它。
有一個Map具有不同功能的模塊來處理這樣的資料結構,它還提供諸如Map.map, Map.filter, Map.fold, Map.find, ... 等內容。所以改用這個。如果確實需要,您還可以使用Map.toList將其再次轉換回串列,或使用Map.fold.
無論如何作為提醒,因為有些人使用(List.zip然后List.map)或(List.zip然后List.fold)。有一個List.map2andList.fold2在一個操作而不是兩個操作中完成此操作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/349040.html
