Python:字符串长度求和

19

在Python中,是否有比使用循环更习惯的方法来计算字符串长度的总和?

length = 0
for string in strings:
    length += len(string)

我尝试了sum(),但它只适用于整数:

>>> sum('abc', 'de')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]

1
“更快”是什么意思?是指打字更少还是执行更快? - Richard Cook
@Richard:抱歉,我想到“更快”是指打字更少,但实际上我的意思是符合习惯用语。 - Zaz
1
没关系,我想其他人都明白了。我只是一个吹毛求疵的人! - Richard Cook
8个回答

49
length = sum(len(s) for s in strings)

这绝对是一种更习惯的表达方式,但我认为在计算上它并不更有效率。尽管如此,因为优雅和Pythonicness而加1分! - Richard Cook
1
如果你真的很担心计算效率,那么你可能不应该使用Python,或者应该用C或C++编写计算密集型部分(如果你勇敢的话,可以使用SciPy的编织库)。我喜欢这种风格,因为它对其他Python开发人员更易读。 - Mike DeSimone
谢谢,这比我的代码短得多,也更容易理解。 - Zaz

18

我第一种方法是sum(map(len, strings))。另一种方法是像其他答案中所述,使用列表推导式或生成器表达式。


回答不错,但我接受了liori的答案,因为我觉得它更符合习惯用语。 - Zaz
@Josh:大多数人确实会发现genexp更具有Python风格。我只是想为了完整性而补充一下。 - Daenyth

7

最短且最快的方法是应用函数式编程风格,使用map()sum()

>>> data = ['a', 'bc', 'def', 'ghij']
>>> sum(map(len, data))
10

在Python 2中,为了获得更好的内存性能,请使用itertools.imap代替map
>>> from itertools import imap
>>> data = ['a', 'bc', 'def', 'ghij']
>>> sum(imap(len, data))
10

5
我知道这是一个老问题,但我不能不提醒你Python错误信息会“告诉”你如何实现这一点:
TypeError: sum() can't sum strings [use ''.join(seq) instead]

那么:

>>> strings = ['abc', 'de']
>>> print len(''.join(strings))
5

当你不必这样做时,连接字符串似乎是浪费的,但是因为增加了另一种解决问题的方式,所以加1分! - Zaz
我不知道 - 我早就停止想知道代码是否对非实时系统浪费CPU资源。但是既然你提到了“少打字”,这看起来相当紧凑。 - Auspex
1
@Zaz 浪费?如果timeit模块可信,则这是三种解决方案中最快的。你接受的答案sum(len(s) for s in strings)慢了三倍以上,也比sum(map(len, strings))慢近两倍。(当然,在Python中速度并不重要--如果你想要速度,你会使用Pypy,正如俗话所说--但是相对于其他方法,完整的生成器表达式在我看来也有点难看。) - user4698348
1
其他答案更通用和有用,因为它们还回答了当列表的元素类型不是字符串时的问题。 - aggieNick02
1
@aggieNick02 其他答案回答了一个并未被问到的问题!问题是关于字符串列表的,而答案则由错误信息提供。为什么要过度复杂化呢? - Auspex
显示剩余3条评论

2
print(sum(len(mystr) for mystr in strings))

1

简述

如果你关心性能,请使用

len(''.join(strings))

否则,使用map将足以满足需求,而不会牺牲代码的可读性或大量的性能。
sum(map(len, strings))

性能指标

尽管我同意普遍共识,即在使用Python时,您的首要任务不应该是编写高效和可扩展的代码,但我认为为本文提供一些建议答案的时间记录会很有益。

使用lorem ipsum第一段的文字(为简洁起见,字符串列表被排除在外)

In [3]: timeit("""
    ...: length = 0
    ...: for s in strings:
    ...:     length += len(s)
    ...: """, globals=globals())
Out[3]: 5.197531974001322

In [4]: timeit("sum(len(s) for s in strings)", globals=globals())
Out[4]: 4.925184353021905

In [5]: timeit("sum(map(len, strings))", globals=globals())
Out[5]: 1.9876644779578783

In [6]: timeit("len(''.join(strings))", globals=globals())
Out[6]: 0.6793132669990882

因此,在处理大量字符串时,@Auspex 显然是更好的选择。


1
这里有另一种使用运算符的方法。不确定这是否比被接受的答案更易读。
import operator

length = reduce(operator.add, map(len, strings))

print length

-1

补充一下...

将存储为字符串的列表中的数字相加

nos = ['1','14','34']

length = sum(int(s) for s in nos)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接