3

I've this list with tuples:

l = [('a','b'),('c','d'),('e','f')]

And two parameters: a key value, and a new value to modify. For example,

key = 'a'
new_value= 'B' # it means, modify with 'B' the value in tuples where there's an 'a'

I've this two options (both works):

f = lambda t,k,v: t[0] == k and (k,v) or t 
new_list = [f(t,key,new_value) for t in l]
print new_list 

and

new_list = []
for i in range(len(l)):
    elem = l.pop()
    if elem[0] == key:
        new_list.append((key,new_value))
    else:
        new_list.append(elem)
print new_list

But, i'm new in Python, and don't know if its right.

Can you help me? Thank you!

Tom Zych
  • 13,329
  • 9
  • 36
  • 53
santiagobasulto
  • 11,320
  • 11
  • 64
  • 88
  • 5
    If you want dictionary-like features, use a [dictionary](http://docs.python.org/tutorial/datastructures.html#dictionaries). Obviously this means keys have to be unique; I don't know if that goes against your requirements – NullUserException Sep 04 '11 at 23:29
  • Thank you, i know dictionary. It's a more general question, how to modify elements in a list. – santiagobasulto Sep 04 '11 at 23:32
  • This doesn't modify a. List, it creates a new copy. Which do you want? – Kathy Van Stone Sep 04 '11 at 23:35
  • @Kathy you're right! I'd like to know both. to modify i'd do pop(i), and insert(i,x). What do you think? – santiagobasulto Sep 04 '11 at 23:36
  • there are different ways to modify lists in python because different situations work best with the different approaches. There is no general answer to the best way to modify a list. – Winston Ewert Sep 04 '11 at 23:57
  • possible duplicate of [How to modify list entries during for loop?](http://stackoverflow.com/questions/4081217/how-to-modify-list-entries-during-for-loop) – Dana the Sane Sep 05 '11 at 00:01

4 Answers4

4

Here is one solution involving altering the items in-place.

def replace(list_, key, new_value):
    for i, (current_key, current_value) in enumerate(list_):
        if current_key == key:
            list_[i] = (key, new_value)

Or, to append if it's not in there,

def replace_or_append(list_, key, new_value):
    for i, (current_key, current_value) in enumerate(list_):
        if current_key == key:
            list_[i] = (key, new_value)
            break
    else:
        list_.append((key, new_value))

Usage:

>>> my_list = [('a', 'b'), ('c', 'd')]
>>> replace(my_list, 'a', 'B')
>>> my_list
[('a', 'B'), ('c', 'd')]

If you want to create a new list, a list comprehension is easiest.

>>> my_list = [('a', 'b'), ('c', 'd')]
>>> find_key = 'a'
>>> new_value = 'B'
>>> new_list = [(key, new_value if key == find_key else value) for key, value in my_list]
>>> new_list
[('a', 'B'), ('c', 'd')]

And if you wanted it to append if it wasn't there,

>>> if len(new_list) == len(my_list):
...     new_list.append((find_key, new_value))

(Note also I've changed your variable name from l; l is too easily confused with I and 1 and is best avoided. Thus saith PEP8 and I agree with it.)

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
3

To create a new list, a list comprehension would do:

In [102]: [(key,'B' if key=='a' else val) for key,val in l]
Out[102]: [('a', 'B'), ('c', 'd'), ('e', 'f')]

To modify the list in place:

l = [('a','b'),('c','d'),('e','f')]

for i,elt in enumerate(l):
    key,val=elt
    if key=='a':
        l[i]=(key,'B')
print(l)              
# [('a', 'B'), ('c', 'd'), ('e', 'f')]
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Wow, didn't know those "inline ifs" nor enumerate function. Thanks! – santiagobasulto Sep 05 '11 at 12:31
  • @santiagobasulto: glad I could help. The "inline ifs" are called [conditional expressions](http://docs.python.org/reference/expressions.html#conditional-expressions) or ternary expressions in Python. – unutbu Sep 05 '11 at 12:37
2

To modify existing list just use list assignment, e.g.

>>> l = [('a','b'),('c','d'),('e','f')]
>>> l[0] = ('a','B')
>>> print l
[('a', 'B'), ('c', 'd'), ('e', 'f')]

I would usually prefer to create a new list using comprehension, e.g.

[(key, new_value) if x[0] == key else x for x in l]

But, as the first comment has already mentioned, it sounds like you are trying to make a list do something which you should really be using a dict for instead.

wim
  • 338,267
  • 99
  • 616
  • 750
2

Here's the approach I would use.

>>> l = [('a','b'),('c','d'),('e','f')]
>>> key = 'a'
>>> new_value= 'B'
>>> for pos in (index for index, (k, v) in enumerate(l) if k == key):
...     l[pos] = (key, new_value)
...     break
... else:
...     l.append((key, new_value))
... 
>>> l
[('a', 'B'), ('c', 'd'), ('e', 'f')]

This looks an awful lot like an OrderedDict, though; key-value pairs with preserved ordering. You might want to take a look at that and see if it suits your needs

Edit: Replaced try:...except StopIteration: with for:...break...else: since that might look a bit less weird.

SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • You do go in for a complicated solution! – Chris Morgan Sep 04 '11 at 23:57
  • I don't consider this to be complicated at all. `list.index` is not available because we're looking for an element that is *in some way similar* to the key, rather than equal to the key. `enumerate` is pretty normal, and I know of no alternative idiom to get the *first element* from a generator besides `.next()` and catching the exception when not found. Other alternatives would either be needlessly wordy, or generate intermediate lists. – SingleNegationElimination Sep 05 '11 at 00:10
  • I would call it complicated in the way that the Zen of Python talks of complex being better than complicated. When there is a simple solution - iterating with a full `for` loop rather than using `.next()` and having to deal with catching a `StopIteration` - it's often better. I had to think briefly about what your solution was doing to verify its correctness, whereas I can look at my solution or the other similar ones that have been posted and understand what is being done immediately. It seems to me that error in the `for-if` style would be much more obvious. – Chris Morgan Sep 05 '11 at 00:22
  • Interesting solution and discussion! Thank you! – santiagobasulto Sep 05 '11 at 12:32