3

If I have a list:

my_list = [3,2,2,3,4,1,3,4]

and a tuple

my_tuple = (3,5)

What's the best way of replacing elements in my_list using the tuple:

result = [5,2,2,5,4,1,5,4]

e.g.

for item in my_list:
    if(item == my_tuple[0]):
        item = my_tuple[1]

More generally, I would have a list of lists, and a list of tuples, and I would like to apply each of the tuples to each of the lists within the list of lists.

5
  • The approach in your example is basically sound, except that the assignment won't work because you're working on a copy of the value in the list. You need to enumerate the list and replace the value at the correct index if your criterion is met. (List comprehensions are better for the simple case, but may get ugly for the list of lists and list of tuples). Commented Jan 30, 2012 at 16:27
  • I still get confused as to when python makes copies and uses references ... Commented Jan 30, 2012 at 16:42
  • Don't be confused, it's really very simple: Python always uses references. Commented Jan 30, 2012 at 17:13
  • Except that item in the above is a copy! Commented Jan 30, 2012 at 17:19
  • 1
    item will actually be a reference to the elements in my_list, but since my_list contains only immutable types it won't really matter. If my_list was a list of lists you could do something like item[:] = [1, 2] and modify the contents of my_list. Commented Jan 30, 2012 at 17:30

4 Answers 4

11

The more natural data structure for my_tuple is a dictionary. Consider something like this and use the .get() method:

>>> my_lists = [[3,2,2,3,4,1,3,4], [1,2,3,4,5,6]]
>>> my_tuple_list = [(3,5), (6, 7)]
>>> my_dict = dict(my_tuple_list)
>>> my_dict
{3: 5, 6: 7}
>>> my_lists = [[my_dict.get(x,x) for x in somelist] for somelist in my_lists]
>>> my_lists
[[5, 2, 2, 5, 4, 1, 5, 4], [1, 2, 5, 4, 5, 7]]
Sign up to request clarification or add additional context in comments.

2 Comments

get(x, x) ... that's beautiful!
Perfect! Hadn't thought of using a dictionary, makes perfect sense.
3

Per @Wooble's comment, your code will work if you enumerate.

list_of_lists = [[3,2,2,3,4,1,3,4], [1,3,5,3,4,6,3]]
list_of_tuples = [(3,5), (1,9)]

def tup_replace(mylist, mytuple):
    for i, item in enumerate(mylist):
        if item == mytuple[0]:
            mylist[i] = mytuple[1]
    return mylist

then you can just nest that some more to work on a list of list and list of tuples.

for mylist in list_of_lists:
    for mytuple in list_of_tuples:
        mylist = tup_replace(mylist, mytuple)
    print mylist

That said, the dictionary approach is probably better.

1 Comment

+1, because I think it makes more sense for there to be a variety of answers with different approaches (even if some are less efficient) than a bunch of similar answers which evolve into each other. IMHO each question usually should have at least two answers: one, explaining how to fix the apparent problem in the OP's code, and two, explaining how the OP should really have solved the problem in the first place.
1

Using if item == my_tuple[0], ... in a general case sounds like you are making a switch statement that you want to apply to each item in your list. Use a dictionary instead if you can. (Why isn't there a switch or case statement in python?)

Convert your list of tuples to a lookup dictionary (python's switch statement):

replacements = dict(my_tuples) #thanks to @julio

Then for a single list, reproduce the list with a comprehension, but replace each value with the new value from replacements if it exists:

replaced_list = [replacements.get(original,original) for original in my_list]

I guess there is a more efficient way to do it, but that's for a single list with a list of tuples. You say you also need to do it for a list of lists? Just nest that?

Could you explain more about where you are getting this data and why you need to do it?

2 Comments

More pythonic: replacements = dict(my_tuples)
I didn't know that. Thanks and I will update the answer. More importantly, I missed the case of not having all items in the replacements.
1

If you are trying to replace every 3 in your list with 5, this will do:

[x == my_tuple[0] and my_tuple[1] or x for x in my_list]

If you want to do this, with more than one "translational" tuple, then I really suggest to use a dictionary instead:

trans = {3: 5, 4: 6}
[trans.get(x,x) for x in my_list]

And in the more general case where you have more than one list:

ll = [[3, 2, 3, 4], [5, 4, 3, 4]]
trans = {3: 5, 4: 6}
for i in range(len(ll)):
    ll[i] = [trans.get(x,x) for x in ll[i]]

Supposing that you want to replace every old list in ll with the new one.

1 Comment

@PlatinumAzure: The OP asked how to do this and more generally with multiple lists and translate tuples. I've just updated my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.