我有两个清单:
a=[[10, 0], [12,1], [13, 8], [2, -3]]
b=[1, 2, -30, 404]
我想将a[*][1]
值替换为b
中的值,以便我的结果如下所示:
[[10, 1], [12, 2], [13, -30], [2, 404]]
一种显而易见的方式(对我来说,真的是一个 C - 程序员)会是这样的:
for i in range(len(a)):
a[i][1]=b[i]
但不知何故,这感觉不是非常pythonic。
我怎么用pythonic方式做到这一点?
此外,b
- 列表可以包含比a
更多或更少的元素。如果数量较少,则a
中的其余元素应保持不变。
a=[[10, 0], [12,1], [13, 8], [2, -3]]
b=[10, 20]
result=[[10, 10], [12,20], [13, 8], [2, -3]]
如果他们更多,我想添加带有默认第一个元素的新条目(例如None
)
a=[[10, 0], [12,1]]
b=[100, 200, -30, 404]
result=[[10, 100], [12,200], [None, -30], [None, 404]]
这可以通过列表推导来实现吗?
答案 0 :(得分:2)
使用zip
和列表理解:
>>> a[:] = [[x, z] for (x, y), z in zip(a, b)]
>>> a
[[10, 1], [12, 2], [13, -30], [2, 404]]
对于长度不一致的案例,您可以使用iterools.izip_longest
:
>>> from itertools import izip_longest
>>> a = [[10, 0], [12,1], [13, 8], [2, -3]]
>>> b = [10, 20]
>>> sen = object()
#len(a) > len(b)
>>> a[:] = [[x, y if z is sen else z]
for (x, y), z in izip_longest(a, b, fillvalue=sen)]
>>> a
[[10, 10], [12, 20], [13, 8], [2, -3]]
>>> a = [[10, 0], [12,1]]
>>> b = [100, 200, -30, 404]
#len(b) > len(a)
>>> a[:] = [[None if x is sen else x , z]
for (x, y), z in izip_longest(a, b, fillvalue=[sen]*2)]
>>> a
[[10, 100], [12, 200], [None, -30], [None, 404]]
如果您认为列表推导太难以理解,请使用generator function
:
def solve(a, b):
sen = object()
if len(a) == len(b):
for (x, y), z in zip(a, b):
yield [x, z]
elif len(a) > len(b):
for (x, y), z in izip_longest(a, b, fillvalue=sen):
yield [x, y if z is sen else z]
else:
for (x, y), z in izip_longest(a, b, fillvalue=[sen]*2):
yield [None if x is sen else x , z]
<强>演示:强>
>>> list(solve([[10, 0], [12,1], [13, 8], [2, -3]], [1, 2, -30, 404]))
[[10, 1], [12, 2], [13, -30], [2, 404]]
>>> list(solve([[10, 0], [12,1], [13, 8], [2, -3]], [10, 20]))
[[10, 10], [12, 20], [13, 8], [2, -3]]
>>> list(solve([[10, 0], [12,1]], [100, 200, -30, 404]))
[[10, 100], [12, 200], [None, -30], [None, 404]]
答案 1 :(得分:2)
enumerate
通常被认为是循环遍历列表索引范围的pythonic替代方法。除此之外,你的解决方案真的没什么特别的。
for i, v in enumerate(b):
try:
a[i][1] = v
except IndexError:
a.append([None, v])
或者,使用迭代器来避免多个try / catch触发器:
bnumer = enumerate(b)
for i, v in bnumer:
try:
a[i][1] = v
except IndexError:
break
# extend the list with the remaining default values from b
a.extend([None,v] for v in bnumer)
答案 2 :(得分:1)
尝试使用列表推导:
if len(a) > len(b):
result = [[e[0], b[i]] if i < len(b) else e for i, e in enumerate(a)]
else:
result = [[a[i][0], e] if i < len(a) else [None, e] for i, e in enumerate(b)]
以上考虑了问题中描述的三种情况,它是否更加pythonic是否由你来判断 - 但它产生正确的结果,这才是最重要的。