用Python求和非整数([[1],[2]])= [1,2]

dou*_*oug 3 python sum

是否可以在python中获取非整数的总和?

命令

sum([[1],[2]])
Run Code Online (Sandbox Code Playgroud)

例如,给出错误

Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    sum([[1,2,3],[2,3,4]])
TypeError: unsupported operand type(s) for +: 'int' and 'list'
Run Code Online (Sandbox Code Playgroud)

我怀疑sum会尝试将0添加到列表[1],导致失败.我确信有很多黑客可以解决这个限制(在一个类中包装东西,并__radd__手动实现),但有更优雅的方法来做到这一点吗?

Gab*_*abe 9

看起来你想要这个:

>>> sum([[1],[2]], [])
[1, 2]
Run Code Online (Sandbox Code Playgroud)

你是对的,它试图将0添加到[1]并收到错误.解决方案是给出sum一个额外的参数给出起始值,对于你来说这将是空列表.

编辑:正如gnibbler所说,sum并不是连接事物的好方法.如果你只想聚合一系列事物,你应该使用reduce而不是__radd__仅仅使用自己的功能sum.这是一个例子(具有相同的不良行为sum):

>>> reduce(lambda x, y: x+y, [[1],[2]])
[1, 2]
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 8

使用sum()除数字之外的任何东西都是一个坏主意,因为它具有序列/字符串/等的四元性能.

最好使用列表理解来汇总列表

[j for i in [[1],[2]] for j in i]
Run Code Online (Sandbox Code Playgroud)

  • @delnan,除了`sum()`不这样做,它创建一个全新的`list`,它是每次迭代的两个串联,因此是二次行为 (2认同)

ken*_*ytm 5

连接使用更有效itertools.chain.

>>> m = [[i] for i in range(200)]
>>> m
[[0], [1], [2], [3], [4], [5], [6], [7], [8], ...]
>>> from itertools import *
>>> list(chain(*m))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ...]
Run Code Online (Sandbox Code Playgroud)

就个人而言,我更喜欢这个而不是列表理解,因为很难记住哪个for循环首先出现.甚至还有一种更有效的变种list(chain.from_iterable(m)).

Microbenchmark结果(Python 3使用timeit模块.列表大小为p x q表示m = [list(range(q)) for _ in range(p)]):

list size | chain(*m)  | sum(m,[])     | list comp  | flatten    |
----------+------------+---------------+------------+------------+
    2 x 1 |   1.78 µs  |      0.646 µs |   0.905 µs |    1.49 µs |
   20 x 1 |   4.37 µs  |      7.49  µs |   5.19  µs |    3.59 µs |
  200 x 1 |  26.9  µs  |    134     µs |  40     µs |   24.4  µs |
 2000 x 1 | 233    µs  | 12.2       ms | 360     µs | 203     µs |
----------+------------+---------------+------------+------------+
 2 x    1 |   1.78 µs  |      0.646 µs |   0.905 µs |    1.49 µs |
 2 x   10 |   2.55 µs  |      0.899 µs |   3.14  µs |    2.2  µs |
 2 x  100 |   9.07 µs  |      2.03  µs |  17.2   µs |    8.55 µs |
 2 x 1000 |  51.3  µs  |     21.9   µs | 139     µs |   49.5  µs |
----------+------------+---------------+------------+------------+

chain(*m) -> list(chain(*m))
sum(m,[]) -> sum(m, [])
list comp -> [j for i in m for j in i]
flatten   -> icfi = chain.from_iterable; list(icfi(m))
Run Code Online (Sandbox Code Playgroud)

它表明只有在外部列表大小很短时才sum有效.但是你有一个更有效的变体:.m[0]+m[1]