我需要你的帮助,我有一个这样的结构:
myList = [(1,2,3),(2,4,4),(1,5,6)]
它是一个元组列表。现在我需要获得列表中每个元组的每个第一个元素,例如将每个1
替换为3
。
输出应为:myList = [(3,2,3),(2,4,4),(3,5,6)]
我知道我可以让它像:
for item in myList:
if item[0] == 1:
item[0] = 3
但是有其他的方法吗?不用遍历整个列表?
类似:myList.getFirstItemOfEachTuple.replace(1,3)
编辑:如果需要的话,我可以把myList
改成[[1,2,3,4,5,6]...]
。
>>> myList = [(1,2,3,4,5,6),(4,5,6,7,8)]
>>> dic = {1:3}
>>> [ (dic.get(x[0],x[0]),) + x[1:] for x in myList]
[(3, 2, 3, 4, 5, 6), (4, 5, 6, 7, 8)]
如果myList
是一个列表的列表:
>>> myList = [[1,2,3,4,5,6],[4,5,6,7,8]]
>>> [ [dic.get(x[0],x[0]) ] + x[1:] for x in myList]
[[3, 2, 3, 4, 5, 6], [4, 5, 6, 7, 8]]
修改原列表:
>>> myList[:] = [(dic.get(x[0],x[0]),) + x[1:] for x in myList]
>>> myList
[(3, 2, 3, 4, 5, 6), (4, 5, 6, 7, 8)]
但是有其他的方法吗?不用遍历整个列表?
。除非遍历整个列表
由于希望检查每个元组以查看希望更改的元素是否为某个数字,因此必须以某种方式遍历整个列表。所以剩下唯一要考虑的就是如何去做。
存在良好的、经过时间考验的和行业标准的指导方针来帮助决定如何编写代码:在编写代码时,您应该将代码可读性作为第一优先级。代码效率远远排在第二位。这条规则也有例外,但它们与这里无关。
看看你的原始代码。它假设item
是list
,所以我也将:
for item in myList:
if item[0] == 1:
item[0] = 3
现在与Ashwini的建议进行比较:
dic = {1: 3}
myList[:] = [[dic.get(x[0], x[0])] + x[1:] for x in myList]
现在问你自己:
- 哪一个最容易阅读和理解?我认为答案是显而易见的。
- 哪个更有效率?
让我们看看效率:
您的原始代码:对于
myList
中的每个项目,执行单个列表查找,然后可能执行单个列表赋值,这两个操作都非常快。Ashwinis code:重建整个结构。对于
myList
中的每个项目,python需要创建三个新列表(五个如果你想更改一个不是第一个的项目)。Python必须为每个列表分配新内存,并对大量旧列表进行垃圾收集,这两个操作都相当慢。这一切都是为了把它塞进一行代码。
请使用原始代码。原因:
- 这是显而易见的方法。
- 这是python的方法。
- 这是最易读的方式。
- 这是最有效的方法。
这意味着这是正确的方法。
如果你想要一个单行代码,让它成为一个函数:
def conditional_sublist_assign(myList, index, from, to):
"""
For each `item` in `myList`, set `item[index] = to` if `item[index] == from`.
"""
for item in myList:
if item[index] == from:
item[index] = to
# Here's your one-liner:
conditional_sublist_assign(myList, 0, 1, 3)
为了让我的论点更有说服力,下面是《Python之禅》中的一些相关台词:
- 美总比丑好。
- 简单比复杂好。
- 可读性。
- 应该有一个——最好只有一个——明显的方法来做到这一点。
- 如果实现很难解释,这是一个坏主意。
使用列表推导式。
条件第一个元组项必须为1:
>>> L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [[3] + x[1:] if x[0] == 1 else x for x in L]
[[3, 2, 3], [4, 5, 6], [7, 8, 9]]
用元组代替列表中的列表的解决方案:
>>> L = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [(3,) + x[1:] if x[0] == 1 else x for x in L]
[(3, 2, 3), (4, 5, 6), (7, 8, 9)]
你可以在numpy中这样做,numpy比python快50倍,所以如果速度很重要,这绝对是你的选择:
import numpy as np
myList = [(1,2,3),(2,4,4),(1,5,6)]
# convert list of tuples to 2D numpy array
myList = np.array(myList)
# get an array of all first element, syntax: myList[x, y] x and w and be ranges 1:3 og numbers like 1
# all the first elements are as follows:
first = myList[:,0]
# you can then make a true / false vector as follows
myList[first == 1,0] = 3
print myList
# prints:
#[[3 2 3]
# [2 4 4]
# [3 5 6]]
你不能改变tuple的值,它是不可变的。但是将元组转换为列表并更改值