How to conditionally replace items in a list
I wanted to replace items in a list based on a specific condition. For example, given a list of numbers, I want to replace all items that are negative with zero.
At first, I thought of something like this:
mylist = [111, -222, 333, -444] newlist =  for item in mylist: if item < 0: item = 0 newlist.append(item) mylist = newlist print mylist
Which gave me the expected results:
[111, 0, 333, 0]
Then I tried using Python's
previous example) built-in function
to replace the item in-line. This seems to be a more elegant solution
to me. Is there a better way? How would you do it?
mylist = [111, -222, 333, -444] for (i, item) in enumerate(mylist): if item < 0: mylist[i] = 0 print mylist
[111, 0, 333, 0]
- Python data object motivated by a desire for a mutable namedtuple with default values — posted 2012-08-03
- How to sort a list of dicts in Python — posted 2010-04-02
- Python setdefault example — posted 2010-02-09
- How to use Python's enumerate and zip to iterate over two lists and their indices. — posted 2008-04-18
- How to invert a dict in Python — posted 2008-01-14
10 Comments — Comments feed for this post
#1 Alejandro commented on 2008-08-22:
mylist = [x*(x>=0) for x in mylist]
#2 Harsh commented on 2008-08-23:
Or readably: map(lambda x: 0 if x<0 else x, mylist)
#3 Sofeng commented on 2008-08-24:
Alejandro and Harsh,
Thanks for the feedback. I definitely like the conciseness of list comprehensions and the map/lambda combination. I suppose the "if x<0 else x" expression allows for other general conditional tests besides my specific example. As another alternative, I could combine that expression with a list comprehension and write: mylist = [0 if x<0 else x for x in mylist]
My bigger question is, what should I do if I have multiple statements within my "if" condition? For example, the actual code that I was writing was this:
for (i, parent) in enumerate(parent_list):
....if parent['id'] == parent_pk:
........parent_list[i] = parent
(note, I replaced the leading spaces with periods due to the limitations in my commenting system. yeah, I know, I ought to update my commenting system. I was kind of hoping Django would do it for me).
If I tried to make this into one list comprehension, I think I would start to lose readability. I really like the functional/declarative style of Python programming but I don't know how to migrate complex loop+conditional logic. Do I need to break it up into multiple declarative statements?
#4 Alexander Artemenko commented on 2008-08-27:
I suppose, that you variant with "max" is more readable:
map(lambda x: max(0,x), mylist)
For multiple ifs, you can write separate function and pass it to the map or in the list comprehension instead of lambda.
#5 Alexander Artemenko commented on 2008-08-27:
Please, add an atom link (http://www.saltycrane.com/feeds/latest/) to the HTML template, and any rss reader can autodiscover your feed.
#6 Sofeng commented on 2008-08-27:
Alexander, Thanks for the comments. Passing a separate function to the map or list comprehension sounds good. I will have to keep that in mind the next time I come across something similar.
Regarding the feed link, is there something wrong with my Atom at the bottom of my right sidebar? Is there a problem because I use a relative URL?
#7 Angela commented on 2008-09-04:
alright! good job...hehehe
#8 Angela commented on 2008-09-04:
i found a little "blip" here...once i commented i couldn't go back to the original page to read my own comment...hmmm...
#9 Eliot commented on 2008-09-04:
yeah, I know this is a problem. unfortunately, I don't know how to fix it. if I figure out anything, I will make the change.