【问题标题】:F# iteration over a Dictionary字典上的 F# 迭代
【发布时间】:2011-03-17 02:31:57
【问题描述】:

我刚开始使用 F#,我想遍历字典,获取键和值。

所以在 C# 中,我会写:

IDictionary resultSet = test.GetResults;
foreach (DictionaryEntry de in resultSet)
{
    Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

我似乎找不到在 F# 中执行此操作的方法(无论如何都不能编译)。

有人可以建议 F# 中的等效代码吗?

干杯,

暗恋

【问题讨论】:

    标签: f#


    【解决方案1】:
    resultSet |> Map.iter (fun key value ->
       printf "Key = %A, Value = %A\n" key value)
    

    【讨论】:

    • 很好奇 - printf 在字符串末尾带有 \n 而不仅仅是 printfn 的任何原因?
    • 每当我看到printfn 时,我都会问相反的问题。没有理由,当然,只是个人喜好。
    【解决方案2】:

    你的字典是什么类型的?

    如果它是非泛型 IDictionary 如您的代码 sn-p 建议的那样,请尝试以下操作(在 F# 中,for 不会隐式插入转换,因此您需要添加 Seq.cast<> 以获取类型您可以轻松使用的集合):

    for entry in dict |> Seq.cast<DictionaryEntry> do
      // use 'entry.Value' and 'entry.Key' here
    

    如果您使用通用 IDictionary&lt;'K, 'V&gt;,则不需要调用 Seq.cast(如果您对库有任何控制权,这比上一个选项更好):

    for entry in dict do
      // use 'entry.Value' and 'entry.Key' here
    

    如果您使用不可变 F# Map&lt;'K, 'V&gt; 类型(如果您在 F# 中编写函数式代码,这是最好使用的类型),那么您可以使用 Pavel 的解决方案,或者您可以将 for 循环与KeyValue 活动模式如下:

    for KeyValue(k, v) in dict do
      // 'k' is the key, 'v' is the value
    

    在这两种情况下,您都可以使用for 或各种iter 函数。如果您需要执行具有副作用的操作,那么我更喜欢for 循环(这不是我提到这个的第一个答案:-)),因为这是为此目的设计的语言结构。对于功能处理,您可以使用各种功能,例如Seq.filter 等。

    【讨论】:

    • 对方法 (function?) 的循环调用很好,但有副作用。
    • 但是iter 的全部意义也是为了执行副作用(从它的类型可以看出),所以它也是“为此目的而设计的”......(这并不是说当然,for 是劣等的;事实上,我只是不知道 KeyValue)。
    • @Pavel:是的,iter 也是为此目的而设计的。但是,我的印象是 iter 是从 OCaml 继承的,而 F# 的做法是使用 for(不过这可能是个人喜好)。一般来说,如果你在做适合语言结构的事情,我认为语言结构比库函数更可取。
    • iter 的优势在于,当您在做一堆其他事情时(例如 filtermap),它与管道语法很好地融合在一起 - 作为最后一步,它清晰可见在管道中,而 for 它从其余部分中脱颖而出。另一方面,它是可咖喱的。所以我不认为这只是一个遗留问题(最终,如果只是这样,它就不会出现在 Seq 中)。然后是iteriiter2 和朋友,它们确实具有for 中不存在的一些额外功能(除非你首先使用zipmapi)——一旦你开始使用它们,简单的iter 就是更一致。
    • @Pavel:与管道一起工作的要点很好。在这种情况下,我也使用iter(以及在处理事件时使用Observable.add)。 Currying 是另一个好点(我偶尔也会使用 iter,当我可以使用 currying 时)。但是,我也看到使用iter 使代码看起来更“实用”的代码,唯一的结果是它看起来不太可读......我认为人们必须更加小心 F# 中的可读性(因为它是也许(?)更容易编写看起来很可怕的代码)
    【解决方案3】:

    (这是一个比 Tomas 更短的答案,直奔主题。)字典是可变的,在 F# 中使用 Maps(不可变)更自然。因此,如果您正在处理 map: Map&lt;K,V&gt;,请以这种方式遍历它:

    for KeyValue(key,value) in map do
        DoStuff key value
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-01
      • 2021-08-26
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多