0

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

myList = [(1,2,3),(2,4,4),(1,5,6)]

这是一个元组列表。现在我需要获取列表中每个元组的每个第一个元素,例如13.

输出应该是: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]...]

4

5 回答 5

5
>>> 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)]
于 2013-05-31T08:56:28.463 回答
3

但是还有其他方法可以做到这一点吗?不遍历整个列表?

不,不是没有遍历整个列表。

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

存在良好的、经过时间考验的和行业标准的指南来帮助决定如何编写代码:在编写代码时,您应该将代码的可读性作为首要任务。代码效率排在第二位。这条规则有例外,但它们在这里不相关。

看看你的原始代码。它假设item是 a 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 代码:重建整个结构。对于myListpython 中的每个项目,需要创建三个新列表(如果要更改不是第一个的项目,则为五个)。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)

为了让我的论点更有分量,以下是 Python Zen of Python中的一些相关行:

  • 美丽总比丑陋好。
  • 简单胜于复杂。
  • 可读性很重要。
  • 应该有一种——最好只有一种——明显的方法来做到这一点。
  • 如果实现很难解释,那是个坏主意。
于 2013-05-31T09:39:27.733 回答
1

With list comprehensions.

Condition first tuple item must be 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]]

Solution for tuples instead of lists inside the list:

>>> 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)]
于 2013-05-31T08:58:15.103 回答
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]]
于 2013-05-31T10:40:29.807 回答
0

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

于 2013-05-31T09:03:55.477 回答