-2

I have a list of integers, it looks like this:

[10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]

I need for this list, for every 0, it to stay 0 and every higher number to be 1. Thus converting the above list to:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1]

I tried to use the following code:

for numbers in list:
   if number==0:
      number=0
   if number>1:
      number=1

however this gives me:

 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Shifu
  • 2,115
  • 3
  • 17
  • 15

7 Answers7

14
>>> l = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
>>> [1 if x > 0 else 0 for x in l]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1]

if you want to change existing list

for i, x in enumerate(l):
    if x >= 1: l[i] = 1
Roman Pekar
  • 107,110
  • 28
  • 195
  • 197
11

A simple list-comprehension

>>> l = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
>>> [1 if i else 0 for i in l]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1]

The reason your code was not working is because you are iterating (looping) through each item of the list, but not modifying the item in the original list, only the returned item.


Timers (In order of speed):

# my method: [1 if i else 0 for i in l]
>>> timeit.Timer('[1 if i else 0 for i in l]', setup='from __main__ import l').repeat()
[1.4960370266417915, 1.457976119063474, 1.457053021255831]
# Roman Pekar: [1 if x > 0 else 0 for x in l]
>>> timeit.Timer('[1 if x > 0 else 0 for x in l]', setup='from __main__ import l').repeat()
[1.5296303022631434, 1.5041486202146075, 1.51295106957906]
# inspectorG4dget: [int(i>0) for i in myList]
>>> timeit.Timer('[int(i>0) for i in l]', setup='from __main__ import l').repeat()
[5.0810576000558285, 4.865218180917736, 4.7859557786252935]
# Haidro: map(int, map(bool, l))
>>> timeit.Timer('map(int, map(bool, l))', setup='from __main__ import l').repeat()
[5.725813168085608, 5.759308116913473, 5.549817013103507]
# alecxe: map(lambda x: int(x > 0), l)
>>> timeit.Timer('map(lambda x: int(x > 0), l)', setup='from __main__ import l').repeat()
[7.054628605392196, 7.291914272244128, 7.223923128993391]
# inspectorG4dget: [int(bool(i)) for i in l]
>>> timeit.Timer('[int(bool(i)) for i in l]', setup='from __main__ import l').repeat()
[8.60473766374804, 8.537255398342722, 8.545150893104449]
Inbar Rose
  • 41,843
  • 24
  • 85
  • 131
  • If the numbers are not guaranteed to be non-negative, you'll need to use one of the versions that explicitly compare to 0. – chepner Jul 22 '13 at 13:21
  • 1
    In which case, as timed above, [Roman Pekar's answer](http://stackoverflow.com/a/17788107/1561176) would be best suited. However, in the OP's question the function is written without a condition for what happens to negative numbers, also - it seems to be this is an attempt to "normalize" a list of values to those `with` a value and those `without` a value. A very common operation in mathematics. If this is not the case, I would be surprised. – Inbar Rose Jul 22 '13 at 13:23
8
myList = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
newList = [int(i>0) for i in myList]

OR

newList = [int(bool(i)) for i in myList]
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
2

You can use map instead of list comprehension approach:

>>> l = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
>>> map(lambda x: int(x > 0), l)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1]

Also see: Python List Comprehension Vs. Map

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
1

You are using numbers variable when creating a for loop, but then you are comparing number (no 's') variable.

Also, avoid using list as a list name; give it some other name (e.g. a_list, or something descriptive).

Others have already provided you with good answers. Just in case you have a hard time understanding list comprehensions, this is what you tried to do:

old_list = [1, 5, 0, 0, 2]
new_list = []
for each_element in old_list:
    if each_element == 0:
        new_list.append(0)
    else:
        new_list.append(1) # what about negative numbers?

This is equivalent to:

new_list = [0 if each_element == 0 else 1 for each_element in a_list]

You can also "modify" (overwrite) existing list on the fly:

a_list = [0 if each_element == 0 else 1 for each_element in a_list]
blablatros
  • 733
  • 1
  • 7
  • 21
  • 1
    Why was this upvoted? I encourage the upvoter to run the code and see what happens. Hint: `number` is a local variable set to each value in the list, not some magical pointer to the object in the list. Changing it won't change the list. – Wooble Jul 22 '13 at 13:03
  • My bad, I removed the code completely. – blablatros Jul 22 '13 at 13:14
1

Use map:

L = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
print map(int, map(bool, L))

Booleans are subclasses of integers, thus False == 0 and True == 1. Calling int() on a bool will return either one or zero for true or false, respectively.

Note that in Python 3, map returns an iterator. So you should call list() on the outside map()

TerryA
  • 58,805
  • 11
  • 114
  • 143
0

How about this:

nums = [10, 8, 4, 4, 13, 1, 1, 1, 1, 6, 1, 2, 1, 1, 0, 1, 5, 1, 5, 5, 2, 1, 0, 0, 4]
for i in range(len(nums)):
    if nums[i]: nums[i] = 1
rnbguy
  • 1,369
  • 1
  • 10
  • 28