【问题标题】:Counting occurrences of words using functional programming使用函数式编程计算单词的出现次数
【发布时间】:2017-07-11 14:13:15
【问题描述】:

任务

给定一个字符串列表,其中可能包含一个或多个单词,我如何使用函数式编程来创建词频词典?通过函数式编程,我明确指的是mapfilterreduce 的使用。此外,表格理解也属于函数式编程。


代码

def count_individual_words(word_list):
    word_count = {x: y.count(x) for y in word_list for x in y.split()}
    return word_count

tweets = ["I am a cat", "cat", "Who is a good cat"]

for i,v in count_individual_words(tweets).items():
    print(i,v)

#Expected Output (dict)
# => {
# "I": 1,
# "am": 1,
# "a": 2,
# "cat": 3,
# "Who": 1,
# "is": 1,
# "good": 1 }

主要问题

主要问题出现在计算出现多次的单词时,例如 cata .问题是,它不是在当前字数上加一,而是用一覆盖字数。因此,最后,我得到的字典显示所有单词只出现一次。

如果有人提到使用 mapfilterreduce,我将非常感谢,因为我很好奇如何使用这些给定函数中的任何一个来完成这项任务。

【问题讨论】:

  • word_list 是什么?
  • 你需要collections.Counter

标签: python dictionary functional-programming itertools


【解决方案1】:

基本上这就是collections.Counter 的用途。但是如果你想自己创建字典,你也可以使用集合模块中的defaultdict 函数:

In [17]: from collections import defaultdict

In [18]: d = defaultdict(int)

In [20]: for sent in tweets:
             for word in sent.split():
                 d[word] += 1
   ....:         

In [21]: d
Out[21]: defaultdict(<class 'int'>, {'a': 2, 'is': 1, 'good': 1, 'am': 1, 'I': 1, 'cat': 3, 'Who': 1})

另一种效率不高的方法是使用列表推导和字典推导:

In [36]: all_words = [i for sub in tweets for i in sub.split()]

In [37]: {word: all}
all        all_words  

In [37]: {word: all_words.count(word) for word in set(all_words)}
Out[37]: {'a': 2, 'is': 1, 'Who': 1, 'am': 1, 'I': 1, 'cat': 3, 'good': 1}

使用函数式编程执行此操作可能如下所示:

In [38]: unique = set(all_words)

In [39]: dict(zip(unique, map(all_words.count, unique)))
Out[39]: {'a': 2, 'is': 1, 'Who': 1, 'am': 1, 'I': 1, 'cat': 3, 'good': 1}

【讨论】:

  • 但这不是使用函数式编程
  • @Jean-FrançoisFabre 为了完整起见,请更新。
  • 好的,很好。但正如你所说Counter 是最好的方法,函数式编程并不总是最好的选择。
【解决方案2】:

最合乎逻辑的方法也使用函数式编程,但只提供给collections.Counter

import collections,itertools
collections.Counter(itertools.chain.from_iterable(x.split() for x in tweets))

如果您在不使用Counter 的情况下进行计数/累积,这里有另一种方法:

  • 生成链接/排序的单词列表
  • 将它们分组并生成字典,计算出现次数

代码:

import itertools

tweets = ["I am a cat", "cat", "Who is a good cat"]

words = sorted(list(itertools.chain.from_iterable(x.split() for x in tweets)))
count = {k:len(list(v)) for k,v in itertools.groupby(words)}

结果:

{'cat': 3, 'I': 1, 'Who': 1, 'is': 1, 'am': 1, 'a': 2, 'good': 1}

这甚至可以是单行的,但可读性会受到影响

(请注意list 被强制进入sorted 以加快操作速度)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    • 2021-11-17
    相关资源
    最近更新 更多