【问题标题】:Python sum of ASCII values of all characters in a string字符串中所有字符的 ASCII 值的 Python 总和
【发布时间】:2012-09-11 14:38:27
【问题描述】:

我正在寻找一种更有效的方法来总结给定字符串中所有字符的 ASCII 值,仅使用标准 python(最好是 2.7)。

目前我有:

print sum(ord(ch) for ch in text)

我想强调的是,我在上面写的这个问题的主要重点和方面。

以下是这个问题不太重要的方面,应该这样对待

那我为什么要问它?!我已经将这种方法与嵌入一个简单的 C 代码函数进行了比较,后者使用 PyInline 执行相同的 here,似乎一个简单的 C 嵌入函数快 17 倍。

如果没有比我建议的更快的 Python 方法(仅使用标准 Python),那么 Python 开发人员没有在核心中添加这样的实现似乎很奇怪。

建议答案的当前结果。 在我的 Windows 7、i-7、Python 2.7 上:

 text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 sum(ord(ch) for ch in text)
 >> 0.00521324663262
 sum(array.array("B", text))
 >> 0.0010040770317
 sum(map(ord, text ))
 >> 0.00427160369234
 sum(bytearray(text))
 >> 0.000864669402933

 C-code embedded:
 >> 0.000272828426841

【问题讨论】:

  • 为什么这样的函数应该成为 Python 核心的一部分?我看不到它的一般用途......
  • @Tim Pietzcker:在对字符串进行哈希处理时经常使用字符串的 ascii 值的总和,例如滚动哈希函数
  • @Michael 只有一个非常差的哈希值才会对这些值进行直接求和,通常会涉及到权重。而且,正如所指出的,最好使用更高级别的接口(如hash()),然后 that 可以在 C 中。
  • @Michael:我并没有不同意,我只是想问为什么这样的功能足够有用,可以包含在核心语言中。
  • 这个问题有两个有争议的主张:一个,它将纯 Python 代码与嵌入式 C 代码进行比较,其中嵌入式 C 代码甚至不处理简单的溢出。因此,这种比较是无用的,并且会偏离问题。其次,在语言中包含这样的求和函数而不给出单个用例的建议是完全愚蠢的。 (由于展开解释的原因,哈希用例不计算在内。)在可预见的未来,对 Python 核心的每一项添加都会带来维护和教学负担,并且需要被可证明的用例覆盖。

标签: python string python-2.7 ascii


【解决方案1】:

您可以使用中间 bytearray 来加快速度:

>>> sum(bytearray("abcdefgh"))
804

这并不比生成器快 17 倍——它涉及创建中间 bytearraysum 仍然需要迭代 Python 整数对象——但在我的机器上它确实加快了对 8 个字符的字符串求和的速度从2μs到约700ns。如果对于您的用例来说,这种情况下的时间安排仍然太低效,那么您应该无论如何都应该用 C 来编写应用程序的速度关键部分。

如果您的字符串足够大,并且可以使用numpy,则可以通过使用numpy.frombuffer 直接引用字符串的缓冲区来避免创建临时副本:

>>> import numpy as np
>>> np.frombuffer("abcdefgh", "uint8").sum()
804

对于较小的字符串,这比临时数组慢,因为 numpy 的视图创建机制很复杂。然而,对于足够大的字符串,frombuffer 方法开始得到回报,当然它总是产生更少的垃圾。在我的机器上,截断点是大约 200 个字符的字符串。

另外,请参阅 Guido 的经典文章 Python Optimization Anecdote。虽然它的一些特定技术现在可能已经过时,但关于如何思考 Python 优化的一般课程仍然非常相关。


您可以使用 timeit 模块为不同的方法计时:

$ python -m timeit -s 's = "a" * 20' 'sum(ord(ch) for ch in s)' 
100000 loops, best of 3: 3.85 usec per loop
$ python -m timeit -s 's = "a" * 20' 'sum(bytearray(s))'
1000000 loops, best of 3: 1.05 usec per loop
$ python -m timeit -s 'from numpy import frombuffer; s = "a" * 20' \
                      'frombuffer(s, "uint8").sum()' 
100000 loops, best of 3: 4.8 usec per loop

【讨论】:

  • +1,谢谢,我搜索的这种类型的答案,我现在检查一下
  • 我已经测试过了,它比我建议的要快,因此这是一个很好的答案,它仍然比嵌入式 c 版本慢。
  • 在 python 3 中同样有效,你只需要使用字节文字:sum(array.array("B", b"abcdefgh"))
  • 与 Python 模式的完美搭配。结语涵盖了这个确切的情况(减去sum 电话)!
  • 你可以避免import arraysum(array.array('B', 'abcdefgh'))在使用2.7时只写sum(bytearray('abcdefgh'))
【解决方案2】:

您可以通过删除生成器的创建来加快它的速度(大约 40%,但远不及原生 C)...

代替:

sum(ord(c) for c in string)

做:

sum(map(ord, string))

时间安排:

>>> timeit.timeit(stmt="sum(map(ord, 'abcdefgh'))")
# TP: 1.5709713941578798
# JC: 1.425781011581421
>>> timeit.timeit(stmt="sum(ord(c) for c in 'abcdefgh')")
# TP: 1.7807035140629637
# JC: 1.9981679916381836

【讨论】:

  • +1 ,你的权利,它稍微快一点,但数组方法最快,我已经编辑了问题以呈现当前结果。
【解决方案3】:
print sum(map(ord,my_string))

这将是最简单的。

【讨论】:

    【解决方案4】:

    打印字符串中字符的 ASCII 值之和

    首先将所有字符串转换为列表,每个单词都分开。然后使用 ord() 函数将每个字符转换为 ascii 并将它们存储在列表中,然后将所有列表值相加。

    str1 = input("Please Enter your Own String : ")
    li=[] 
    li[:0]=str1 
    print(li)
    result=[]
    for i in range(len(li)):
        result.append(ord(li[i]))
        result = list(set(result))
    print(result)   
    final=sum(result) 
    print("The sum of the your string '{}'is: {}".format(str1,final))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 2021-12-28
      • 2010-12-04
      相关资源
      最近更新 更多