【问题标题】:Counting frequency of string or float in a list计算列表中字符串或浮点数的频率
【发布时间】:2013-10-14 20:30:19
【问题描述】:

我有一个清单。它相当大。它有超过 100 万个条目。我想计算其中每个字符串的频率。它将数字存储为从 1 到 1000 的字符串。我使用了以下内容,但它会持续运行数小时:

d = {b:a.count(b) for b in a}
n, m = d.keys(), d.values()
print n, m

【问题讨论】:

  • 问题是,要构建dict,您正在执行n 次(列表长度a)成本na.count(b) 必须迭代所有a 搜索 bs)。这意味着构建它需要与n^2 成正比的时间。如果您有一个包含 100 万个条目的列表,则您必须执行 (10^6)^2 = 10^12 操作。即使单个操作是机器指令,构建它也需要大约 10^3 秒。实际上,每个操作可能需要一些(或至少)数十个机器指令,因此您必须等待数小时/数天。

标签: python list python-2.7 count frequency


【解决方案1】:

改用collections.Counter

from collections import Counter
d = Counter(a)

n, m = d.keys(), d.values()
print n, m

【讨论】:

    【解决方案2】:

    这很慢,因为您要为每个字符串运行 a.count!

    l = ['a', 'b', 'a']
    

    然后str.count 将在“a”上被调用两次,在“b”上被调用 1 次。

    当然,第二次在“a”上,字典中的结果只是被覆盖了,所以你甚至不会注意到它

    改用默认字典

    from collections import defaultdict
    d = defaultdict(int)
    for obj in your_list:
        d[obj] += 1
    

    或者,再次来自集合模块,计数器http://docs.python.org/2/library/collections.html#counter-objects

    【讨论】:

      【解决方案3】:

      我认为在这种情况下使用字典要容易得多。 插入字典非常快,从字典中检索也一样快。

      这里有一个示例程序可以做到这一点:

      import datetime
      import random
      def create_string(choice, size):
          str = ''
          for i in range(size):
               str = str + random.choice(choice)
          return str
      
      def count_all(strings):
          count_dict = {}
          for i in strings:
              if i not in count_dict:
                  count_dict[i] = 1
              else:
                  count_dict[i] = count_dict[i] + 1
          return count_dict
      
      if __name__ == '__main__':
          all_strings = []
          for i in range(1000000):
              all_strings.append(create_string(['a','b','c'], 4))
      
          start = datetime.datetime.now()
          c_dict = count_all(all_strings)
          end = datetime.datetime.now()
          print 'Took:', end - start
          print 'The count of aacc is ', c_dict['aacc']
      

      它是如何公平的?

      ./speed_test.py
      Took: 0:00:00.219815
      The count of aacc is  12317
      

      一点也不差,嘿? 作为替代选项,要解决 Ant 提到的问题,您希望在进行计数时消除重复项。我们可以为此使用一个集合:

      d = {b:a.count(b) for b in set(a)}
      

      根据我的测试,这不如字典方法快,但不到一秒就足够了。

      【讨论】:

      • 不要使用datetime 来描述性能。使用timeit 模块(可能使用iPython),因为它会正确地花费平均时间。如果你想进行单次基准测试,如果你使用的是 python3.3+,请使用time.perf_counter,因为这是它的目的。
      • 好的,谢谢,我最初确实使用了 timeit,但由于它的设置和代码是作为字符串传入的,我认为它会成为一个不必要的复杂示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 2018-09-25
      • 2016-05-18
      • 2017-04-19
      相关资源
      最近更新 更多