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.
Thanks in advance.
Once a tuple is created, you cannot change its values. Tuples are unchangeable, or immutable as it also is called. But there is a workaround. You can convert the tuple into a list, change the list, and convert the list back into a tuple.
Tuples are unchangeable, meaning that you cannot change, add, or remove items once the tuple is created.
First, convert tuple to list by built-in function list(). You can always update an item to list object assigning new value to element at certain index. Then use another built-in function tuple() to convert this list object back to tuple. Element at index 4 in original tuple has been changed from 25 to 100.
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).
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.
Here's a simple way to do it (require Python 2.5 because it use the ternary operator):
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.
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).
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.
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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With