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

时间:2013-05-31 08:51:58

标签: python list tuples

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

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

5 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:3)

  

但还有其他办法吗?没有迭代整个列表?

没有。并非没有迭代整个列表。

由于您希望检查每个元组以查看您想要更改的元素是否为某个数字,因此 迭代整个列表以某种方式。所以唯一剩下的考虑是如何来做。

存在良好的,经过时间考验的行业标准指南,有助于决定如何编写代码:编写代码时,您应该代码可读性作为第一个优先级。代码效率遥遥领先。这条规则有例外,但它们在这里并不相关。

查看原始代码。它假设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中的每个项目,执行单个列表查找,然后执行单个列表分配,这两个操作都非常快。

    < / LI>
  • Ashwinis代码:重建整个结构。对于myList中的每个项目,python需要创建三个新列表(五个,如果您想要更改不是第一个的项目)。 Python必须为每个列表分配新内存,垃圾收集很多旧列表,这两个操作都很慢。所有这些都是为了把它塞进一个单线。

,请使用原始代码。原因如下:

  • 这是明显的方式。
  • 这是 pythonic 的方法。
  • 这是最易读的方式。
  • 这是最有效的方式。

这意味着它是正确的方式。

如果你想要一个单行,那就把它变成一个功能:

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)

为了给我的论点增加一些权重,这里有一些来自The Zen of Python的相关行:

  • 美丽胜过丑陋。
  • 简单比复杂更好。
  • 可读性很重要。
  • 应该有一个 - 最好只有一个 - 显而易见的方法。
  • 如果实施难以解释,那就不错了。

答案 2 :(得分:1)

使用列表推导。

条件第一元组项必须为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)]

答案 3 :(得分:1)

你可以在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]]

答案 4 :(得分:0)

你无法改变元组的值,它是不可变的。但是您将元组转换为列表并更改值