Python - 更新元组列表中的值

时间:2011-12-19 09:20:16

标签: python

更新元组列表中值的最佳方法是什么?

我目前在下面的代码中执行此操作,但我认为有一种更简洁的方式。

>>> foo = [('a', 'hello'), ('b', 'world')]
>>> bar = dict(foo)
>>> bar['b'] = 'friend'
>>> foo = bar.items()
>>> foo
[('a', 'hello'), ('b', 'friend')]

编辑:使用元组列表的原因在我原来的帖子中并不清楚。 目标是在错误处理期间更新wsgi应用程序的一些标头值,即元组列表。

提前致谢。

4 个答案:

答案 0 :(得分:10)

您的数据结构(元组列表)最好称为关联列表。正如其他人所指出的那样,使用字典可能会更好,因为你可以在操作上获得更好的摊销成本(插入,删除和查找是字典的O(1),但删除和查找是关联的O(n)列表)。

关于通过将关联列表转换为字典来更新关联列表,然后返回到关联列表,此方法有三个缺点。这是非常昂贵的,它可能会改变项目的顺序,它将删除重复。

如果您想继续使用关联列表,最好只使用列表推导来更新数据结构。成本将是O(n)的时间和内存,但这已经是你使用中间字典时的结果。

这是一种简单的方法(需要Python 2.5,因为它使用三元运算符):

def update_in_alist(alist, key, value):
    return [(k,v) if (k != key) else (key, value) for (k, v) in alist]

def update_in_alist_inplace(alist, key, value):
    alist[:] = update_in_alist(alist, key, value)

>>> update_in_alist([('a', 'hello'), ('b', 'world')], 'b', 'friend')
[('a', 'hello'), ('b', 'friend')]

答案 1 :(得分:7)

由于元组是不可变的,你需要用新的元组替换元组。

>>> foo[1] = (foo[1][0], "friend")
>>> foo
[('a', 'hello'), ('b', 'friend')]

当然,这只有在您知道要替换的项目的索引时才有效。如果您拥有的只是第一个项目的值,那么在列表中搜索该索引并不高效,尤其是对于较大的列表。上面的示例也是如此 - 将列表转换为dict并返回仅更改一些条目不是可扩展的解决方案。

正如eumiro和DrTysra在评论中提到的,如果你的数据结构允许,你可能最好只使用一个字典(或OrderedDict如果订单很重要)。

答案 2 :(得分:3)

根据您的使用情况,您似乎真的想要使用字典开头,而不是元组列表。如果您将每个元组的第一个字段视为唯一键,请将其设为字典,以便获得O(1)访问权限并验证密钥是否真正唯一。

否则,您需要搜索以查找要修改的元组的索引,然后使用新元组覆盖该数组中的那个插槽,因为元组本身无法修改。

index = -1
target = "b"
new_value = "friend"
for i, v in enumerate(foo):
  if v[0] == target:
    index = i
    break
if index >= 0:
  foo[index] = (foo[index][0], new_value)

诚然,这有点笨拙但是直截了当,至少应该比你当前的解决方案更快(并且内存不足)。当然,它可以简单地包装成一个封装它的函数。

答案 3 :(得分:2)

我不清楚你想要达到什么目标。无法修改元组,因此您无法将('b', 'world')更改为其他内容。但您可以修改课程列表:

foo[1] = ('b','friend')

这是否有意取决于您的使用案例。如果您向我们提供有关代码实际目的的更多详细信息,我们将能够提出更好的解决方案。