你描述的是一个地图数据结构,所以我会使用一个,而不是用一堆列表函数自己实现它,你可以以这种方式转换你的两个列表
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 对象
{
"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 的原因。您使用List.fold2 遍历列表中的每个(key,value),然后将其添加到地图数据结构中。如果键不存在(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.map2 和 List.fold2 在一次操作中完成此操作,而不是两次。