简体   繁体   English

Python - 更新元组列表中的值

[英]Python - Update a value in a list of tuples

What is the best way to update a value in a list of tuples? 更新元组列表中的值的最佳方法是什么?

I currently do it like in the code below, but I suppose there is a cleaner and concise way. 我目前在下面的代码中这样做,但我想有一种更简洁的方式。

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

Edit: The reason to use a list of tuple wasn't clear in my original post. 编辑:使用元组列表的原因在我的原始帖子中并不清楚。 The goal is to update some headers values of a wsgi application during error handling, that are a list of tuples. 目标是在错误处理期间更新wsgi应用程序的某些标头值,即元组列表。

Thanks in advance. 提前致谢。

Your data structure (a list of tuple) is best referred as an associative list. 您的数据结构(元组列表)最好称为关联列表。 As other pointed out, it is probably better to use a dictionary as you'll get better amortized cost on operation (insertion, deletion, and lookup are O(1) for a dictionary, but deletion and lookup are O(n) for associative list). 正如其他人所指出的那样,使用字典可能会更好,因为你可以在操作上获得更好的摊销成本(插入,删除和查找是字典的O(1),但删除和查找是关联的O(n)列表)。

Concerning updating your associative list by converting it to a dictionary, and then back to an associative list, this method has three drawbacks. 关于通过将关联列表转换为字典来更新关联列表,然后返回到关联列表,此方法有三个缺点。 It is quite expensive, it may change the order of the items, and it will remove duplicate. 这是非常昂贵的,它可能会改变项目的顺序,它将删除重复。

If you want to keep using associative lists, it is probably better to just use a list comprehension to update the data structure. 如果您想继续使用关联列表,最好只使用列表推导来更新数据结构。 The cost will be O(n) in time and memory, but that's already what you have when using an intermediate dictionary. 成本将是O(n)的时间和内存,但这已经是你使用中间字典时所拥有的。

Here's a simple way to do it (require Python 2.5 because it use the ternary operator): 这是一种简单的方法(需要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')]

Since tuples are immutable, you'll need to replace the tuple with a new one. 由于元组是不可变的,因此您需要用新元组替换元组。

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

Of course, this only works if you know the index of the item you wish to replace. 当然,这只有在您知道要替换的项目的索引时才有效。 If all you have is the value of the first item, then searching through the list for that index is not efficient especially for larger lists. 如果您拥有的只是第一个项目的值,那么在列表中搜索该索引并不高效,尤其是对于较大的列表。 The same goes for your example above -- converting a list to a dict and back just to change a few entries is not a scalable solution. 上面的示例也是如此 - 将列表转换为dict并返回仅更改几个条目不是可扩展的解决方案。

As eumiro and DrTysra mentioned in the comments, if your data structure allows it, you might be better off simply using a dict (or OrderedDict if order is important). 正如eumiro和DrTysra在评论中提到的那样,如果你的数据结构允许它,你可能最好只使用一个字典(或OrderedDict,如果顺序很重要)。

From your usage, it seems you really want to use a dictionary to begin with, not a list of tuples. 根据您的使用情况,您似乎真的想要使用字典开头,而不是元组列表。 If you're treating the first field of each tuple as a unique key, make it a dictionary so you get O(1) access and validation that the keys are really unique. 如果您将每个元组的第一个字段视为唯一键,请将其设为字典,以便获得O(1)访问权限并验证密钥是否真正唯一。

Otherwise, you need to search to find the index of the tuple to modify, and then overwrite that slot in the array with a new tuple, since tuples themselves cannot be modified. 否则,您需要搜索以查找要修改的元组的索引,然后使用新元组覆盖该数组中的那个插槽,因为元组本身无法修改。

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)

This is, admittedly, a bit clumsy but otherwise straight-forward and should at least be a bit faster (and less memory-hungry) than your current solution. 不可否认,这有点笨拙但是直截了当,至少应该比你当前的解决方案更快(并且内存不足)。 It can trivially be wrapped into a function to encapsulate it, of course. 当然,它可以简单地包装成一个封装它的函数。

It's not perfectly clear to me what you want to achieve. 我不清楚你想要达到什么目标。 Tuples cannot be modified, so you cannot change ('b', 'world') to something else. 元组无法修改,因此您无法将('b', 'world')更改为其他内容。 But you can modify the list of course: 但是你可以修改课程列表:

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

Whether that makes sense or not depends on your use case. 这是否有意取决于您的用例。 If you give us more details about the actual purpose of the code, we would be able to propose better solutions. 如果您向我们提供有关代码实际目的的更多详细信息,我们将能够提出更好的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM