是否有F#等同于Python的Counter集合?

时间:2018-09-04 12:17:37

标签: python f# counter

试图将一些Python代码移植到F#。我是这两种语言的新手。 Python代码使用“ Counter”集合“元素存储为字典键,其计数存储为字典值”。例如在Python中:

cnt = Counter()

for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']
   cnt[word] += 1

cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

>> # Tally occurrences of words in a list
>> cnt = Counter()

>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:

>> ... cnt[word] += 1

>> cnt

>> Counter({'blue': 3, 'red': 2, 'green': 1})

有F#等同于Python的Counter集合吗?

1 个答案:

答案 0 :(得分:4)

在F#中,可能会发生诸如cnt[word] += 1之类的状态突变,但是通常可以避免。取而代之的是,计算是通过使用高阶函数来描述操作的意图,而不是使用命令式命令来描述机制。在这种情况下,典型的F#解决方案可能看起来像这样:

let counts =
    ["red"; "blue"; "red"; "green"; "blue"; "blue"]
    |> List.groupBy id
    |> Map.ofList
    |> Map.map (fun _ words -> words |> List.length)

在这里,我们使用相同的单词列表,然后使用List.groupBy创建列表列表,然后将其传递给id函数,以表示我们希望按值分组自己(列表中的单词)。单词列表实际上是List.groupBy的第二个参数,但是我们使用|>(“管道转发”)运算符将前一个值作为最后一个参数传递给下一个函数。这很有用,因为它使我们可以将操作链接在一起,就像我们在下一行看到的那样,在这里我们获取List.groupBy返回的列表的列表,并将其传递给Map.ofList,这给了我们{ {1}}。

Map<string, string list>类型使我们可以通过键进行查找,例如Map类型。然后,通过将Counter的结果传递到Map<string, string list>中,将Map<string, int>转换为Map.ofList并用每个单词的计数将它转换为{从一种类型到另一种类型的地图。在这种情况下,我们希望将值从Map.map转换为string list,因此我们采用int(我们将其称为“单词”)并将其传递给{{ 1}}来计数。 string list的功能参数采用两个参数,即键和值,但是我们仅对值感兴趣,因此我通过将键参数称为List.length忽略了键参数。这给了我们Map.map,其中包含该单词作为关键字,而列表中该单词的计数作为值:

_

编辑

正如评论中提到的kvb一样,F#Map<string, int>模块已经具有val counts : Map<string,int> = map [("blue", 3); ("green", 1); ("red", 2)] 函数,该函数为您组合了ListcountBy。这使代码更加简单:

groupBy

与上面的结果相同,这是因为我们获取List.length元组的列表并将其通过管道传递到let counts = ["red"; "blue"; "red"; "green"; "blue"; "blue"] |> List.countBy id |> Map.ofList ,这样我们就可以获得地图的查找功能(例如Python {{ 1}}对象)。