【问题标题】:How do you count occurrences in a list in Python?如何计算 Python 列表中出现的次数?
【发布时间】:2019-12-04 00:12:01
【问题描述】:

我是 python 新手,我想计算每个单词在所有文件中出现的次数。显示每个单词,它出现的次数和出现的时间百分比。对列表进行排序,使出现频率最高的单词首先出现,最不频繁出现的单词最后出现。 我正在处理小样本,只知道一个文件,但我无法正常工作,

 from collections import defaultdict

words = "apple banana apple strawberry banana lemon"

d = defaultdict(int)
for word in words.split():
    d[word] += 1

【问题讨论】:

  • 什么不起作用?从诊断上讲,“我无法正常工作”没有帮助。您能否提供示例输入、预期输出和实际输出(包括回溯,如果抛出异常)?这些是minimal reproducible example 的基础知识。正如@RaySteam 所说,collections.Counter 是您在实际代码中执行此操作的方式,但对于学习练习/家庭作业,您可能希望自己实现它。

标签: python


【解决方案1】:

如上所述,collections 模块中的Counter 类绝对是计数应用程序的最佳选择。

此解决方案还解决了使用fileinput.input() 方法迭代所有在命令行上指定的文件名的内容的多个文件中的单词计数请求(或者如果在命令行上没有指定文件名,那么将从STDIN 读取,通常是键盘)

最后,它使用了一种更复杂的方法,以正则表达式作为分隔符将行分成“单词”。如代码中所述,它将更优雅地处理收缩(但是它会被使用单引号的撇号混淆)

"""countwords.py
   count all words across all files
"""

import fileinput
import re
import collections

# create a regex delimiter that is any character that is  not 1 or
# more word character or an apostrophe, this allows contractions
# to be treated as a word (eg can't  won't  didn't )
# Caution: this WILL get confused by a line that uses apostrophe
# as a single quote: eg 'hello' would be treated as a 7 letter word

word_delimiter = re.compile(r"[^\w']+")

# create an empty Counter

counter = collections.Counter()

# use fileinput.input() to open and read ALL lines from ALL files
# specified on the command line, or if no files specified on the
# command line then read from STDIN (ie the keyboard or redirect)

for line in fileinput.input():
    for word in word_delimiter.split(line):
        counter[word.lower()] += 1   # count case insensitively

del counter['']   # handle corner case of the occasional 'empty' word

# compute the total number of words using .values() to get an
# generator of all the Counter values (ie the individual word counts)        
# then pass that generator to the sum function which is able to 
# work with a list or a generator

total = sum(counter.values())

# iterate through the key/value pairs (ie word/word_count) in sorted
# order - the lambda function says sort based on position 1 of each
# word/word_count tuple (ie the word_count) and reverse=True does
# exactly what it says = reverse the normal order so it now goes
# from highest word_count to lowest word_count

print("{:>10s}  {:>8s} {:s}".format("occurs", "percent", "word"))

for word, count in sorted(counter.items(),
                          key=lambda t: t[1],
                          reverse=True):
    print ("{:10d} {:8.2f}% {:s}".format(count, count/total*100, word))

示例输出:

$ python3 countwords.py
I have a dog, he is a good dog, but he can't fly
^D

occurs   percent word
     2    15.38% a
     2    15.38% dog
     2    15.38% he
     1     7.69% i
     1     7.69% have
     1     7.69% is
     1     7.69% good
     1     7.69% but
     1     7.69% can't
     1     7.69% fly

还有:

$ python3 countwords.py text1 text2
    occurs   percent word
         2    11.11% hello
         2    11.11% i
         1     5.56% there
         1     5.56% how
         1     5.56% are
         1     5.56% you
         1     5.56% am
         1     5.56% fine
         1     5.56% mark
         1     5.56% where
         1     5.56% is
         1     5.56% the
         1     5.56% dog
         1     5.56% haven't
         1     5.56% seen
         1     5.56% him

【讨论】:

    【解决方案2】:

    正如cmets中提到的,这正是collections.Counter

    words = 'a b c a'.split()
    print(Counter(words).most_common())
    

    来自文档:https://docs.python.org/2/library/collections.html

    most_common([n])
    Return a list of the n most common elements and their counts
    from the most common to the least. If n is omitted or None,
    most_common() returns all elements in the counter.
    Elements with equal counts are ordered arbitrarily:
    
    >>> Counter('abracadabra').most_common(3)
    [('a', 5), ('r', 2), ('b', 2)]
    

    【讨论】:

      【解决方案3】:

      使用您的代码,这是一种更简洁的方法:

      # Initializing Dictionary
      d = {}
      with open(sys.argv[1], 'r') as f:
      
          # counting number of times each word comes up in list of words (in dictionary)
          for line in f: 
              words = line.lower().split() 
              # Iterate over each word in line 
              for word in words: 
                  if word not in d.keys():
                      d[word] = 1
                  else:
                      d[word]+=1
      
      n_all_words = sum([k.values])
      
      # Print percentage occurance
      for k, v in d.items():
          print(f'{k} occurs {v} times and is {(100*v/n_all_words):,.2f}% total of words.')
      
      
      # Sort a dictionary using this useful solution
      # https://stackoverflow.com/a/613218/10521959
      import operator
      sorted_d = sorted(d.items(), key=operator.itemgetter(1))
      

      【讨论】:

      • 你用的是什么版本的python? @nubby
      • 作为参考,在不带参数调用.split()之前不需要.strip();并且sum(d.values()) 在没有列表理解的情况下工作得很好。
      • python 3 但是我修复了 print 语句但是还是不行,这行我没看懂,n_all_words = sum([v for v in k.values])
      • 这里的缩进是否正确? with open... 行之后没有任何缩进。
      • 让我修复@kaya3
      【解决方案4】:

      最直接的方法就是使用 Counter 函数:

      from collections import Counter
      c = Counter(words.split())
      

      输出:

      Counter({'apple': 2, 'banana': 2, 'strawberry': 1, 'lemon': 1})
      

      按顺序排列单词或计数:

      list(c.keys())
      list(c.values())
      

      或将其放入普通字典中:

      dict(c.items())
      

      或元组列表:

      c.most_common()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-16
        • 1970-01-01
        • 1970-01-01
        • 2016-01-09
        • 2018-09-19
        • 2017-03-08
        • 2018-11-15
        相关资源
        最近更新 更多