繁体   English   中英

优化执行时间以检查单词的字符是否在列表python中

[英]Optimizing execution-time to check if chars of a word are in a list python

我正在编写python2.7.15代码来访问单词中的字符。 我如何优化此过程,以便还检查每个单词是否包含在外部列表中?

我已经尝试了两个版本的python2代码:version(1)是我的代码必须执行的扩展版本,而在版本(2)中,我尝试了相同代码的紧凑版本。

chars_array = ['a','b','c']
VERSION (1)
def version1(word):
    chars =[x for x in word]
    count = 0

    for c in chars:
        if not c in chars_array:
            count+=1

    return count
VERSION (2)
def version2(word):
    return sum([1 for c in [x for x in word] if not c in chars_array])

我正在分析一个大型语料库,对于version1,我获得的执行时间为8.56秒,而对于version2,它的执行时间为8.12秒。

最快的解决方案(对于极长的字符串,最快可以提高100倍):

joined = ''.join(chars_array)
def version3(word):
    return len(word.translate(None, joined))

另一个较慢的解决方案,其速度与您的代码大致相同:

from itertools import ifilterfalse
def version4(word):
    return sum(1 for _ in ifilterfalse(set(chars_array).__contains__, word))

时间( s是随机字符串):

In [17]: %timeit version1(s)
1000 loops, best of 3: 79.9 µs per loop

In [18]: %timeit version2(s)
10000 loops, best of 3: 98.1 µs per loop

In [19]: %timeit version3(s)
100000 loops, best of 3: 4.12 µs per loop # <- fastest

In [20]: %timeit version4(s)
10000 loops, best of 3: 84.3 µs per loop

chars_array = ['a', 'e', 'i', 'o', 'u', 'y']words等于56048个英字列表,我所测量的多种变体具有相似的命令在IPython提示符下执行以下操作:

%timeit n = [version1(word) for word in words]

在每种情况下,它都报告“ 10个循环,最好3个”,并且在下面每个函数定义旁边的注释中显示了每个循环的时间:

# OP's originals:

def version1(word):  # 163 ms
    chars =[x for x in word]
    count = 0
    for c in chars:
        if not c in chars_array:
            count+=1
    return count

def version2(word):  # 173 ms
    return sum([1 for c in [x for x in word] if not c in chars_array])

现在让我们通过三个优化来实现version1version2

  • 删除多余的列表理解,而是直接通过word进行迭代;
  • 不使用not in运算符not in而不是否定in运算符的结果;
  • 检查set而不是list )的(非)成员身份。

_

chars_set = set(chars_array)

def version1a(word):  # 95.5 ms
    count = 0
    for c in word:
        if c not in chars_set:
            count+=1
    return count

def version2a(word):  # 104 ms
    return sum([1 for c in word if c not in chars_set])

因此,多行代码实际上比列表理解有一个优势。 但是,这可能取决于单词的长度: version2a必须分配一个与单词长度相同的新列表,而version1a则不需要。 让我们通过对生成器表达式求和而不是对列表求和进行求和,进一步完善version2a以获得相同的优势:

def version2b(word):  # 111 ms
    return sum(1 for c in word if c not in chars_set)

令我惊讶的是,这实际上适得其反,但同样的,效果可能取决于字长。

最后,让我们体验一下.translate()的强大.translate()

chars_str = ''.join(chars_set)

def version3(word):  # 40.7 ms
    return len(word.translate(None, chars_str))

我们有一个明确的赢家。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM