试图将一些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集合吗?
答案 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)]
函数,该函数为您组合了List
和countBy
。这使代码更加简单:
groupBy
与上面的结果相同,这是因为我们获取List.length
元组的列表并将其通过管道传递到let counts =
["red"; "blue"; "red"; "green"; "blue"; "blue"]
|> List.countBy id
|> Map.ofList
,这样我们就可以获得地图的查找功能(例如Python {{ 1}}对象)。