Python 嵌套列表的内置总和
Python built-in sum for nested list
当我完成 leetcode 1313 时,我发现内置 sum
函数的特殊用法。
Leetcode 问题 1313
我们得到一个 nums
整数列表,表示用 运行 长度编码压缩的列表。
考虑每对相邻的元素 [a, b] = [nums[2*i], nums[2*i+1]] (with i >= 0)
。对于每个这样的对,在解压缩列表中有 a
个值为 b
的元素。
Return解压后的列表。
示例 1:
Input: nums = [1,2,3,4]
Output: [2,4,4,4]
Explanation: The first pair [1,2] means we have freq = 1 and val = 2 so we generate the array [2].
The second pair [3,4] means we have freq = 3 and val = 4 so we generate [4,4,4].
At the end the concatenation [2] + [4,4,4,4] is [2,4,4,4].
有一个解决方案使用sum
nums = [1,2,3,4]
g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
print(list(g))
g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
print(sum(g,[]))
输出:
[[2], [4, 4, 4]]
[2, 4, 4, 4]
我的问题
我不知道为什么 sum
可以在这种情况下处理嵌套列表。任何人都可以告诉我吗?或者其他一些函数的行为是这样的?
这是内置 sum
的 official guide。
sum(foo)
简单地使用 +
的定义作为初始值。默认情况下,初始值为 0
,因此 sum(g)
对于列表将失败,因为未定义列表和整数的添加。通过传递 []
的显式初始值,这会强制 sum(foo, [])
等于 foo[0] + foo[1] + ... + foo[n-1] + []
,如观察到的那样。
>>> sum([[1], [2]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> sum([[1], [2]], [])
[1, 2]
此定义的例外情况是您不能将 sum
与 str
值列表一起使用,即使您将 ""
指定为初始值也是如此。这是一个硬编码异常,导致 TypeError
并建议改用 str.join
。
>>> sum(["foo", "bar"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> sum(["foo", "bar"], "")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]
简答
给定的代码片段 运行s 连续列表连接。
工作原理
内置的sum()函数大致是这样工作的:
def sum(iterable, /, start=0):
total = start
for x in iterable:
total = total + x
return total
+
运算符在左侧操作数上调用 __add__
,因此 3 + 4
运行 与 (3).__add__(4)
一样,是对整数的加法运算。同样,[10, 20] + [30, 40, 50]
运行s 作为 [10, 20].__add__([30, 40, 50])
,列表的串联操作。
这是给定示例中的结果:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> result = []
>>> x = next(g)
>>> result = result + x
>>> result
[2]
>>> x = next(g)
>>> result = result + x
>>> result
[2, 4, 4, 4]
为什么这不是一个好主意
连续列表连接在每次添加后生成下一个列表,因此它们 运行 以 O(n**2)
速度,这意味着这是一种二次算法,在给定大输入时 运行 速度过慢。
更好的方法
无需在每一步构建新列表,只需 extend the base list in-place. This runs at O(n)
线性速度:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> result = [] # new list
>>> for x in g:
result.extend(x) # extend in-place
>>> result
[2, 4, 4, 4]
更好的方法
itertools module provides a tool for chaining together iterators。这使得问题变得很简单:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> list(chain.from_iterable(g))
[2, 4, 4, 4]
这个解决方案简短、快速,即使输入量很大也能很好地工作。
当我完成 leetcode 1313 时,我发现内置 sum
函数的特殊用法。
Leetcode 问题 1313
我们得到一个 nums
整数列表,表示用 运行 长度编码压缩的列表。
考虑每对相邻的元素 [a, b] = [nums[2*i], nums[2*i+1]] (with i >= 0)
。对于每个这样的对,在解压缩列表中有 a
个值为 b
的元素。
Return解压后的列表。
示例 1:
Input: nums = [1,2,3,4] Output: [2,4,4,4] Explanation: The first pair [1,2] means we have freq = 1 and val = 2 so we generate the array [2]. The second pair [3,4] means we have freq = 3 and val = 4 so we generate [4,4,4]. At the end the concatenation [2] + [4,4,4,4] is [2,4,4,4].
有一个解决方案使用sum
nums = [1,2,3,4]
g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
print(list(g))
g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
print(sum(g,[]))
输出:
[[2], [4, 4, 4]] [2, 4, 4, 4]
我的问题
我不知道为什么 sum
可以在这种情况下处理嵌套列表。任何人都可以告诉我吗?或者其他一些函数的行为是这样的?
这是内置 sum
的 official guide。
sum(foo)
简单地使用 +
的定义作为初始值。默认情况下,初始值为 0
,因此 sum(g)
对于列表将失败,因为未定义列表和整数的添加。通过传递 []
的显式初始值,这会强制 sum(foo, [])
等于 foo[0] + foo[1] + ... + foo[n-1] + []
,如观察到的那样。
>>> sum([[1], [2]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> sum([[1], [2]], [])
[1, 2]
此定义的例外情况是您不能将 sum
与 str
值列表一起使用,即使您将 ""
指定为初始值也是如此。这是一个硬编码异常,导致 TypeError
并建议改用 str.join
。
>>> sum(["foo", "bar"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> sum(["foo", "bar"], "")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]
简答
给定的代码片段 运行s 连续列表连接。
工作原理
内置的sum()函数大致是这样工作的:
def sum(iterable, /, start=0):
total = start
for x in iterable:
total = total + x
return total
+
运算符在左侧操作数上调用 __add__
,因此 3 + 4
运行 与 (3).__add__(4)
一样,是对整数的加法运算。同样,[10, 20] + [30, 40, 50]
运行s 作为 [10, 20].__add__([30, 40, 50])
,列表的串联操作。
这是给定示例中的结果:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> result = []
>>> x = next(g)
>>> result = result + x
>>> result
[2]
>>> x = next(g)
>>> result = result + x
>>> result
[2, 4, 4, 4]
为什么这不是一个好主意
连续列表连接在每次添加后生成下一个列表,因此它们 运行 以 O(n**2)
速度,这意味着这是一种二次算法,在给定大输入时 运行 速度过慢。
更好的方法
无需在每一步构建新列表,只需 extend the base list in-place. This runs at O(n)
线性速度:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> result = [] # new list
>>> for x in g:
result.extend(x) # extend in-place
>>> result
[2, 4, 4, 4]
更好的方法
itertools module provides a tool for chaining together iterators。这使得问题变得很简单:
>>> nums = [1,2,3,4]
>>> g = ([b] * a for a, b in zip(nums[::2], nums[1::2]))
>>> list(chain.from_iterable(g))
[2, 4, 4, 4]
这个解决方案简短、快速,即使输入量很大也能很好地工作。