2015-04-01 67 views
-1
let dic = Environment.GetEnvironmentVariables() 
dic 
|> Seq.filter(fun k -> k.Contains("COMNTOOLS")) 

無法編譯。 我試過使用Array.filter, Seq.filter, List.filter 我試過只得到dic.Keys來迭代,但F#似乎並不希望我強制將KeyCollection轉換爲IEnumerable如何迭代F#中的散列表?

我試圖向上轉型哈希表到IEnumerable<KeyValuePair<string,string>>

如何走是從Environment.GetEnvironmentVariables()返回的哈希表?

+2

您應指定實際的錯誤,但我懷疑它與'k.Contains'做。 'k'是一個KeyValuePari <,>所以'Contains'不存在 – 2015-04-01 13:43:07

+0

當我在添加更多細節並刪除實際錯誤而不注意的情況下輸入它時,它是:*無法執行文本選擇:IDictionary類型不兼容類型'seq <'a>'* – Maslow 2015-04-01 13:48:16

回答

2

由於Environment.GetEnvironmentVariables()返回非通用IDictionary並在DictionaryEntry存儲鍵/值對,你必須使用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.Key類型爲obj,因此在檢查字符串包含之前必須將其轉換爲字符串。

代替使用高次函數的,序列表達可能是方便的:

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")) 
0

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")) 
+1

第一個代碼塊不能編譯:* DictionaryEntry類型沒有任何適當的子類型,不能用作類型測試或運行時強制的源代碼*第二個塊沒有因爲似乎沒有'System.Collections.Dictionary',並且給出了額外的錯誤:*類型'Microsoft.FSharp.Collections.seq <_>'需要1個類型參數(s),但給出2 *可能應該是'string * string'。 – Maslow 2015-04-01 14:28:35