最优雅的方法来修改嵌套列表的元素

时间:2011-04-15 04:22:12

标签: python nested-lists

我有一个如下所示的2D列表:

table = [['donkey', '2', '1', '0'], ['goat', '5', '3', '2']]

我想将最后三个元素更改为整数,但下面的代码感觉非常难看:

for row in table:
    for i in range(len(row)-1):
        row[i+1] = int(row[i+1])

但我宁愿有一些看起来像:

for row in table:
    for col in row[1:]:
        col = int(col)

我认为应该有一种方法来编写上面的代码,但是切片会创建一个与原始代码分开的迭代器/新列表,因此引用不会继承。

有没有办法获得更多的Pythonic解决方案?

7 个答案:

答案 0 :(得分:20)

for row in table:
    row[1:] = [int(c) for c in row[1:]]

上面看起来更像pythonic吗?

答案 1 :(得分:13)

尝试:

>>> for row in table:
...     row[1:]=map(int,row[1:])
... 
>>> table
[['donkey', 2, 1, 0], ['goat', 5, 3, 2]]

AFAIK,分配到list切片会强制执行操作,而不是创建新的list

答案 2 :(得分:8)

我喜欢Shekhar回答很多。

作为一般规则,在编写Python代码时,如果您发现自己编写了f or i in range(len(somelist)),那么您做错了:

  • 如果您有一个列表,请尝试enumerate
  • 如果您要并行迭代2个或更多列表,请
  • 尝试zipitertools.izip

在您的情况下,第一列是不同的,因此您不能优雅地使用枚举:

for row in table:
    for i, val in enumerate(row):
        if i == 0: continue
        row[i] = int(val)

答案 3 :(得分:3)

只需使用两个参数调用range即可改进您的“丑陋”代码:

for row in table:
    for i in range(1, len(row)):
        row[i] = int(row[i])

如果您坚持在不分配新临时列表的情况下更改项目(通过使用列表解析,map和/或切片),这可能是您可以做的最好的。见Is there an in-place equivalent to 'map' in python?

虽然我不推荐它,但您也可以通过引入自己的就地地图功能使这段代码更加通用:

def inplacemap(f, items, start=0, end=None):
    """Applies ``f`` to each item in the iterable ``items`` between the range
    ``start`` and ``end``."""
    # If end was not specified, make it the length of the iterable
    # We avoid setting end in the parameter list to force it to be evaluated on
    # each invocation
    if end is None:
        end = len(items)
    for i in range(start, end):
        items[i] = f(items[i])

for row in table:
    inplacemap(int, row, 1)

就个人而言,我发现较少 Pythonic。最好只有一种明显的方法,而不是它。

答案 4 :(得分:1)

使用列表推导:

table = [row[0] + [int(col) for col in row[1:]] for row in table]

答案 5 :(得分:0)

这将有效:

table = [[row[0]] + [int(v) for v in row[1:]] for row in table]

但是,您可能想要考虑在首次创建列表时进行转换。

答案 6 :(得分:-1)

这可以实现您的目标。这是一个可读的解决方案。你也可以使用listcomp去寻找类似的。

>>> for row in table:
...     for i, elem in enumerate(row):
...             try:
...                     int(elem)
...             except ValueError:
...                     pass
...             else:
...                     row[i] = int(elem)
...