3

我有两个清单:

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-list 的元素可能比 . 更多或更少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]]

这可以通过列表理解来实现吗?

4

3 回答 3

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如果您认为列表推导太难以理解,请使用 a :

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]]
于 2013-10-02T16:28:37.533 回答
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)
于 2013-10-02T16:30:30.643 回答
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取决于您来判断 - 但它会产生正确的结果,这才是最重要的。

于 2013-10-02T16:36:11.777 回答