我有一份清单清单:
mylist = [['Bob','AA',3,2.1,4],['Sally','BB',2,5.1,3],['Jim','CC',2,1.5,4]]
我需要将元素2和3相乘并将得到的解决方案插入到索引4中,将所有内容移到一起并格式化浮点错误。期望的输出:
mylist = [['Bob','AA',3,2.1,6.3,4],['Sally','BB',2,5.1,10.2,3],['Jim','CC',2,1.5,3,4]]
我几乎用以下方法解决了这个问题:
for i, val in enumerate(mylist):
sol = (float(val[2]*val[3]))
val.insert(4,'%.3f' % sol)
print(mylist)
我得到了:
[['Bob', 'AA', 3, 2.1, 6.300, 4], ['Sally', 'BB', 2, 5.1, 10.200, 3], ['Jim', 'CC', 2, 1.5, 3.000, 4]]
2个问题:
答案 0 :(得分:1)
是否有比我目前的解决方案更加pythonic的方式? (列表理解会很好)
列表理解是一种构建列表的Pythonic方法。将副作用应用于一堆值不是Pythonic方法。 Pythonic的方法是使用for
语句,就像你做的一样。
您的代码没有什么问题,但是,与大多数代码一样,它可以得到改进:
enumerate
值,请不要使用i
;只是循环遍历列表本身。float
值的float
。format
函数通常比str.format
或%
更简单,更易读(也可能更有效,但不太重要)。*
(虽然此处value[2]
位于边线处。)所以:
for value in mylist:
solution = value[2] * value[3]
value.insert(4, format(solution, '.3'))
PEP 8就其中的一些问题提供了一些指导,但并不多。
name, thingy, count, weight, stuffness = value
solution = count * weight
或者:
_, _, count, weight, _ = value
solution = count * weight
另外,鉴于这些东西是固定形状的异构集合,最好将它们存储为元组而不是列表。当然,你正在做的是改变列表,所以这不适用于此。但也许你不应该在第一时间做到这一点。也许最好建立一个新的元组列表。在这种情况下,你实际上可以使用列表理解:
[value + (format(value[2] * value[3], '.3'),) for value in mylist]
......或者,结合最后两个想法:
[(name, thingy, count, weight, stuffness, format(count * weight, '.3'))
for (name, thingy, count, weight, stiffness) in mylist]
这实际上是否更具可读性或更多pythonic是非常有争议的。
答案 1 :(得分:-1)
- 是否有比我目前的解决方案更加pythonic的方式? (列表理解会很好)
醇>
您使用for
循环的方法是正确的,非常" pythonic。"这里只是一个小小的注释:
enumerate()
,则不必使用i
也就是说,如果您有兴趣考虑其他特定于python的替代方案,也可以使用list comprehension。有两种方法:
使用运算符重载的列表理解:
您还可以通过重载+
运算符来使用列表并置。如果你放松新产品进入第四个索引的条件,而不是将输出放在列表的末尾,那么解决方案会更优雅。因此,我们可以用一个列表理解来替换for循环:
myList = [ val + [float( format( val[2]*val[3], '.3f'))] for val in myList ]
这将给我们:
>>> print(myList)
[['Bob', 'AA', 3, 2.1, 4, 6.3], ['Sally', 'BB', 2, 5.1, 3, 10.2], ['Jim', 'CC', 2, 1.5, 4, 3.0]]
您仍然可以使用稍微不那么优雅的配方实现将产品放入第4个指数所需的输出:
myList = [ val[:3] + [float( format( val[2]*val[3], '.3f'))] + val[4:] for val in myList ]
insert()
列表理解:
insert()
函数的工作方式略有不同,所以要小心谨慎。 insert()
在列表推导中使用时,会修改原始列表。因此,您不需要将列表推导分配给新变量。
考虑到这一点,您可以将for循环替换为:
[ val.insert( 4, float( format( val[2] * val[3], '.3f') ) for val in myList ];
这将正确更新您的myList
变量,并像以前一样提供给我们:
>>> print(myList)
[['Bob', 'AA', 3, 2.1, 6.3, 4], ['Sally', 'BB', 2, 5.1, 10.2, 3], ['Jim', 'CC', 2, 1.5, 3.0, 4]]
使用insert()
函数列表理解的注意事项:
;
,在列表理解的末尾需要抑制不必要的输出,否则会导致显示[None, None, None]
。2. How do I correctly format the float errors? (EDIT: Included '%.3f' % at the insert, seems to work ok.)
正如您在上面所看到的,format()
功能在这里效果最好。
关于浮点精度的注释:
format()
函数为数字分配适当的浮点精度,然后将结果字符串转换为float()
,然后适当地剥离尾随的无关零。 float()
,因为在乘法过程中您不会失去任何精度。但是,如果要划分2个列表元素,则必须进行强制转换。在这种情况下,必须首先将除数或被除数转换为float( val[2] )
以确保浮点除法,否则将导致整数除法。