可以修改元组列表中的每个第一个元组元素



我需要你的帮助,我有一个这样的结构:

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)]

但是有其他的方法吗?不用遍历整个列表?

。除非遍历整个列表

由于希望检查每个元组以查看希望更改的元素是否为某个数字,因此必须以某种方式遍历整个列表。所以剩下唯一要考虑的就是如何去做。

存在良好的、经过时间考验的和行业标准的指导方针来帮助决定如何编写代码:在编写代码时,您应该将代码可读性作为第一优先级。代码效率远远排在第二位。这条规则也有例外,但它们与这里无关。

看看你的原始代码。它假设itemlist,所以我也将:

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的值,它是不可变的。但是将元组转换为列表并更改值

最新更新