如何在 F# 中迭代​​哈希表?

How do I iterate over a hashtable in F#?

let dic = Environment.GetEnvironmentVariables()
dic
|> Seq.filter( fun k -> k.Contains("COMNTOOLS"))

编译失败。 我试过使用 Array.filter, Seq.filter, List.filter 我试过只让 dic.Keys 迭代,但 F# 似乎不希望我将 KeyCollection 强制转换为 IEnumerable.

我已经尝试将哈希表升级为 IEnumerable<KeyValuePair<string,string>>

如何遍历从 Environment.GetEnvironmentVariables() 返回的哈希表?

因为 Environment.GetEnvironmentVariables() returns 一个非泛型 IDictionary 并且它在 DictionaryEntry 中存储 key/value 对,你必须使用 Seq.cast第一:

let dic = Environment.GetEnvironmentVariables()

dic
|> Seq.cast<DictionaryEntry>
|> Seq.filter(fun entry -> entry.Key.ToString().Contains("COMNTOOLS"))

请参阅 https://msdn.microsoft.com/en-us/library/system.collections.idictionary(v=vs.110).aspx 中的相关文档。请注意 entry.Keyobj 类型,因此必须在检查字符串包含之前转换为字符串。

不使用高阶函数,序列表达式可能更方便:

let dic = Environment.GetEnvironmentVariables()
seq {
    for entry in Seq.cast<DictionaryEntry> dic ->
        (string entry.Key), (string entry.Value)
}
|> Seq.filter(fun (k, _) -> k.Contains("COMNTOOLS"))

F# Seq 只能与System.Collections.Generic.IEnumerable<_>一起操作。 Environment.GetEnvironmentVariables 返回的 System.IDictionary 不是通用的,但它实现了非通用的 System.Collections.IEnumerable 而不是 System.Collections.Generic.IEnumerable<_>System.Collections.IEnumerable 不包含类型信息并允许枚举装箱类型的集合,即 System.Object 的实例。 无论如何,System.IDictionary 可以枚举为 System.Collections.DictionaryEntry 个对象的集合,因此您可以简单地对其调用 Seq.cast。它会让您访问 KeyValue 属性,但仍作为对象装箱,因此您也应该将它们拆箱。

let dic = System.Environment.GetEnvironmentVariables()
dic
|> Seq.cast<System.Collections.DictionaryEntry>
|> Seq.filter( fun k -> (k.Key :?> string).Contains("COMNTOOLS"))

或者您可以使用以下函数

let asStringPairSeq (d : System.Collections.IDictionary) : seq<string * string> =
    Seq.cast<System.Collections.DictionaryEntry> d
    |> Seq.map (fun kv -> kv.Key :?> string, kv.Value :?> string)

System.Environment.GetEnvironmentVariables()
|> asStringPairSeq
|> Seq.filter (fun (k,v) -> k.Contains("COMNTOOLS"))