【问题标题】:PYTHON: How would a function be made for comparing recurring words within two lists?PYTHON:如何创建一个函数来比较两个列表中的重复单词?
【发布时间】:2018-08-12 17:16:00
【问题描述】:

例如:

q=["hi", "sky"]
p=["here","sky","sky","sky","sky"]

函数会被定义为得到什么:

count_words(["hi", "sky"], ["here","sky","sky","sky","sky"])
[0, 4]
# answer where hi appears 0 times and sky appears 4 times

我是这样开始代码的:

def count_words(q, p):
    count = 0
    for word in q:
        if q==p:
            (q.count("hi"))
            (q.count("sky"))
        return count

我不断得到一个值 0,它占 q,但我无法得到 p 的值。

【问题讨论】:

  • 欢迎来到 SO!如果您可以直接以文本形式发布代码,请避免粘贴屏幕截图

标签: python list function count call


【解决方案1】:

这是一个更简单的答案(更简单的意思是单行且不使用其他库) -

q=["hi", "sky"] 
p=["here","sky","sky","sky","sky"]

def count_words(q,p):
    return [ p.count(i) for i in q ]

print(count_words(q,p))

输出

[0, 4]

说明

[ p.count(i) for i in q ] 是一个list comprehension,这就像在运行中迭代q 列表并计算p 中的各个元素

时间(取决于数据)

# My solution
1.78 µs ± 214 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# @Delirious Solution 1
7.55 µs ± 1.58 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# @ Delirious Solution 2
3.86 µs ± 348 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

【讨论】:

  • 虽然count 是用C 实现的,但是如果可以一次完成,重复遍历p 来计算每个单词似乎效率低下。
  • 当您的代码使用 11min 10sec 运行而 46.5ms 运行其他解决方案时,您遇到了问题。
【解决方案2】:
>>> from collections import Counter
... 
... 
... def count_words(a, b):
...     cnt = Counter(b)
...     return [cnt[word] for word in a]
... 
>>> count_words(["hi", "sky"], ["here", "sky", "sky", "sky", "sky"])
[0, 4]

或者如果你因为某种原因不能使用collections.Counter:

>>> def count_words(a, b):
...     cnt = {}
...     for word in b:
...         try:
...             cnt[word] += 1
...         except KeyError:
...             cnt[word] = 1
...     return [cnt.get(word, 0) for word in a]
... 
>>> count_words(["hi", "sky"], ["here", "sky", "sky", "sky", "sky"])
[0, 4]

编辑:

看起来应该有一些时间来“澄清”哪种解决方案更有效。由于@chrisz 忘记发布他的实际测试代码,我不得不自己做。

不幸的是,Vivek 的代码运行了 11min 10sec,而我的代码只运行了 46.5ms。

In[18]: def vivek_count_words(q, p):
   ...:     return [p.count(i) for i in q]
   ...: 
In[19]: def lettuce_count_words(a, b):
   ...:     cnt = {}
   ...:     for word in b:
   ...:         try:
   ...:             cnt[word] += 1
   ...:         except KeyError:
   ...:             cnt[word] = 1
   ...:     return [cnt.get(word, 0) for word in a]
   ...: 
In[20]: # https://www.gutenberg.org/files/2701/2701-0.txt
   ...: with open('moby_dick.txt', 'r') as f:
   ...:     moby_dick_words = []
   ...:     for line in f:
   ...:         moby_dick_words.extend(line.rstrip().split())
   ...: 
In[21]: len(moby_dick_words)
Out[21]: 215829
In[22]: from random import choice

In[23]: random_words = [choice(moby_dick_words) for _ in range(10)]
In[24]: %timeit vivek_count_words(moby_dick_words, random_words)
31.3 ms ± 99.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In[25]: %timeit lettuce_count_words(moby_dick_words, random_words)
20.7 ms ± 54.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In[26]: random_words = [choice(moby_dick_words) for _ in range(100)]
In[27]: %timeit vivek_count_words(moby_dick_words, random_words)
211 ms ± 642 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[28]: %timeit lettuce_count_words(moby_dick_words, random_words)
20.6 ms ± 68.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In[29]: random_words = [choice(moby_dick_words) for _ in range(1000)]
In[30]: %timeit vivek_count_words(moby_dick_words, random_words)
2.18 s ± 2.12 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[31]: %timeit lettuce_count_words(moby_dick_words, random_words)
22.2 ms ± 97.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In[32]: random_words = [choice(moby_dick_words) for _ in range(10000)]
In[33]: %timeit vivek_count_words(moby_dick_words, random_words)
29.2 s ± 865 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[34]: %timeit lettuce_count_words(moby_dick_words, random_words)
25.7 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In[35]: random_words = [choice(moby_dick_words) for _ in range(100000)]
In[36]: %timeit vivek_count_words(moby_dick_words, random_words)
11min 10s ± 7.51 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[37]: %timeit lettuce_count_words(moby_dick_words, random_words)
46.5 ms ± 68.5 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2019-10-31
    • 2012-01-06
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2018-06-14
    相关资源
    最近更新 更多