更新元组列表中值的最佳方法是什么?
我目前在下面的代码中执行此操作,但我认为有一种更简洁的方式。
>>> foo = [('a', 'hello'), ('b', 'world')]
>>> bar = dict(foo)
>>> bar['b'] = 'friend'
>>> foo = bar.items()
>>> foo
[('a', 'hello'), ('b', 'friend')]
编辑:使用元组列表的原因在我原来的帖子中并不清楚。 目标是在错误处理期间更新wsgi应用程序的一些标头值,即元组列表。
提前致谢。
答案 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')
这是否有意取决于您的使用案例。如果您向我们提供有关代码实际目的的更多详细信息,我们将能够提出更好的解决方案。