我有一个如下所示的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解决方案?
答案 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
zip
或itertools.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)
...