28

我有一个看起来像这样的二维列表:

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 的解决方案?

4

7 回答 7

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

上面看起来更像pythonic吗?

于 2011-04-15T04:36:08.210 回答
13

尝试:

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

AFAIK,分配给list切片会强制操作就地完成,而不是创建一个新的list.

于 2011-04-15T04:29:14.690 回答
8

我非常喜欢 Shekhar 的回答。

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

  • 试试enumerate你是否有一个列表
  • 尝试zip或者itertools.izip如果您有 2 个或更多要并行迭代的列表

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

for row in table:
    for i, val in enumerate(row):
        if i == 0: continue
        row[i] = int(val)
于 2011-04-15T06:40:41.773 回答
3

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

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

map如果您坚持更改项目而不分配新的临时列表(通过使用列表理解、和/或切片),这可能是您能做的最好的事情。请参阅python 中是否存在与“地图”等效的原地?

虽然我不推荐,但你也可以通过引入自己的 in-place map 函数来使这段代码更通用:

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。最好只有一种明显的方法可以做到这一点,但事实并非如此。

于 2011-04-15T04:28:38.283 回答
1

使用列表推导:

table = [row[0] + [int(col) for col in row[1:]] for row in table]
于 2011-04-15T04:28:09.173 回答
0

这将起作用:

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

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

于 2011-04-15T04:38:14.150 回答
-1

这完成了你正在寻找的东西。这是一个可读的解决方案。您也可以使用 listcomp 进行类似的操作。

>>> for row in table:
...     for i, elem in enumerate(row):
...             try:
...                     int(elem)
...             except ValueError:
...                     pass
...             else:
...                     row[i] = int(elem)
... 
于 2011-04-15T04:29:14.607 回答