0

据我所知,元组是不可变的结构,所以如果我有一个元组列表。

list1 = [(1,2,3,4),(2,3,4,5)]

我必须更改元组的第一个元素,然后我必须基本上写:

list1[0] = (2,2,3,4)     not list1[0][0] = 2 because tuple is immutable

对于每个元素,我需要这样做。如果需要定期执行此操作,这是一种有效的操作还是使用列表列表更好?

4

6 回答 6

2

如果您需要修改列表的元素,则使用可变元素。将不可变对象存储在可变容器中不会使对象可变。

至于效率,构建一个新的元组比修改一个列表更昂贵。但是对于大多数操作来说,可读性比运行时性能更重要,所以首先要优化可读性。另请记住,当从外部引用列表列表的元素时,您可能会得到副作用:

l1 = [1, 2, 3]
l2 = ['a', 'b', 'c']

lol = [l1, l2]
lol[0][0] = 0

print(l1)  # prints [0, 2, 3]

更新:为了支持我的效率声明,这里有一些使用 IPython%timeit魔法的时间:

>>> list_of_lists = [[1,2,3,4] for _ in xrange(10000)]
>>> list_of_tuples = map(tuple, list_of_lists)
>>> def modify_lol():
...     for x in list_of_lists:
...         x[0] = 0
...         
>>> def modify_lot():
...     for i, x in enumerate(list_of_tuples):
...         list_of_tuples[i] = (0,) + x[1:]
...         
>>> %timeit modify_lol()
100 loops, best of 3: 6.56 ms per loop
>>> %timeit modify_lot()
100 loops, best of 3: 17 ms per loop

因此,列表列表对于这项任务来说要快 2.6 倍。

于 2013-07-19T15:48:16.137 回答
0

看看你有相当于的直接解决方案

list[0] = (2,) + list[0] [1:]

这应该足以让您以编程方式进行操作。它仍在制作副本,但这相当快,切片元组也是如此。

于 2013-07-19T15:50:17.563 回答
0

如果你这样定义你的变量:

list1 = [[1,2,3,4],[2,3,4,5]]

您将能够像这样更改列表的 elemento 的值:

list1[0][0] = 2

现在您的变量值将是:

list1 = [[2,2,3,4],[2,3,4,5]]
于 2013-07-19T15:50:43.677 回答
0

当您只需要更改特定元素时,效率低下就会出现。例如说你有两个元组。

tup1 = (1, 2, 3, 4)
tup2 = (5, 6, 7, 8)

并且您想将两个元组的第一个元素更改为 9。

tup1 = (9, 2, 3, 4)
tup2 = (9, 6, 7, 8)

这样做的唯一方法是,如果您有一百万个具有不同值的元组都需要以 9 开​​头,那么这种方式显然效率低下,您将必须键入并重新分配所有元组不同的值。

相反,您应该使用列表。

l1 = [1, 2, 3, 4]
l2 = [5, 6, 7, 8]

然后你可以做

list = [l1, l2]
for l in list:
    l[0] = 9

这会将所有第一个元素更改为 9,而无需硬编码一百万个列表。

l1就是现在[9, 2, 3, 4]

l2就是现在[9, 6, 7, 8]

于 2013-07-19T15:50:44.557 回答
0

你有两个选择:

L = [(1,2,3,4),(2,3,4,5)]
L = [tuple([2]+subL[1:]) for subL in L]

这比较慢,因为它必须重新创建所有这些元组。

或者

L = [(1,2,3,4),(2,3,4,5)]
L = [list(i) for i in L] # or L = map(list, L)
for subL in L:
    subL[0] = 2
于 2013-07-19T15:51:30.330 回答
0

如果您知道列表项中只有四个元素,但它们需要是可变的,那么最好的选择(在我看来)是使用一个类:

class WXYZ: # example name, give yours something more sensible to the nature of the code
    def __init__(self, w=0, x=0, y=0, z=0)
        self.w = w
        self.x = x
        self.y = y
        self.z = z

然后您的代码将如下所示:

list1 = [WXYZ(1,2,3,4), WXYZ(2,3,4,5)]
list1[0].w = 2

__iter__如果您需要在for循环中使用它,您还可以轻松添加方法:

    def __iter__(self):
        return iter((w,x,y,z))

或者,如果你想变得聪明,你可以这样做

    def __iter__(self):
        yield w
        yield x
        yield y
        yield z

如果您真的担心内存使用情况(在这种情况下为什么要使用 python?),您可以定义__slots__ = ("w","x","y","z")为分配所需的内存。

于 2013-07-19T15:59:23.067 回答