Reputation: 1237
I have this very simple problem: I need to set the values in list a to 1 for each index in list b:
>>> a=[0, 0, 0, 0]
>>> b=[1, 3]
the desired result then would be:
[0, 1, 0, 1]
The elegant solution, if python was worth its salt, would be this of course:
>>> a[b]=1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not list
But of course that doesn't work... so I've tried the following list comprehensions, but they both produce the same error, as if the comprehension was causing it (on the for):
First the simple version I was really expecting to work:
>>> a[x for x in b] = 1
File "<stdin>", line 1
a[x for x in b] = 1
^
SyntaxError: invalid syntax
Then the slightly more complex version:
>>> a[b[x] for x in range(0,len(b))] = 1
File "<stdin>", line 1
a[b[x] for x in range(0,len(b))] = 1
^
SyntaxError: invalid syntax
Can anyone see what's going on here?
Thanks!
Upvotes: 0
Views: 4081
Reputation: 113814
In [1]: a=[0, 0, 0, 0]
In [2]: b=[1, 3]
In [3]: [ 1 if i in b else a_i for i, a_i in enumerate(a) ]
Out[3]: [0, 1, 0, 1]
Import one module and python is, as you say, worth its salt:
In [1]: from numpy import array
In [2]: a = array([0, 0, 0, 0])
In [3]: b = [1, 3]
In [4]: a[b] = 1
In [5]: a
Out[5]: array([0, 1, 0, 1])
For handling large quantities of data, numpy
is both elegant and fast. If not using numpy
, then Jonathan Hartnagel's for
loop or something like Joel Cornett's BellsAndWhistlesList
would be good solutions.
Upvotes: 7
Reputation: 193
What's wrong with :
for i in b:
a[i] = 1
Or, as suggested by @John1024, using numpy :
from numpy import array
a[b] = 1
Upvotes: 3
Reputation: 1632
how about this:
a = [0,0,0,0]
b = [1,3]
for i in range(len(b)):
a[b[i]] = 1
print a # [0, 1, 0, 1]
Upvotes: 0
Reputation: 24788
Just for kicks:
class BellsAndWhistlesList(list):
def __setitem__(self, key, value):
if hasattr(key, "__iter__") or hasattr(key, "next"):
for i, v in zip(key, value):
super(BellsAndWhistlesList, self).__setitem__(i, v)
else:
super(BellsAndWhistlesList, self).__setitem__(key, value)
Upvotes: 0
Reputation: 7255
I don't think [1 if i in b else v for i,v in enumerate(a)]
is efficient, since it needs to check whether i
is in b
for each i
in enumerate(a)
.
As other answers said, for i in b: a[i] = 1
is the simplest and efficient way, it just set values it needs to directly.
However, if you don't want to use the for
loop, there is another way to use map
instead of it to apply operations to all elements of a list. This implement will introduce an function call for each element, so maybe it's not efficient enough either.
>>> a=[0,0,0,0]
>>> b=[1,3]
>>> import functools
>>> def set_index(x, l):
... l[x] = 1
...
>>> mapfunc = functools.partial(set_index, l=a)
>>> map(mapfunc, b)
[None, None]
>>> a
[0, 1, 0, 1]
Upvotes: 0
Reputation: 4318
Using list comprehension:
a = [1 if i in b else v for i,v in enumerate(a) ]
output:
[0, 1, 0, 1]
Upvotes: 1
Reputation: 80011
Try numpy if you want stuff like this:
In [1]: import numpy
In [2]: a = numpy.zeros(4)
In [3]: b = numpy.array((1, 3))
In [4]: a[b] = 1
In [5]: a
Out[5]: array([ 0., 1., 0., 1.])
Or plain Python solutions like these:
a = [0] * 4
b = [1, 3]
for i in b:
a[i] = 1
Alternatively (slow and inefficient):
a = [0] * 4
b = [1, 3]
a = [i in b and 1 or a_i for i, a_i in enumerate(a)]
Upvotes: 1
Reputation: 95948
[x for x in b]
Will create:
[1, 3]
So your code will look like:
a[1,3] = 1
Which is invalid.
I wouldn't use list comprehension for this, you can simply:
for i in b:
a[i] = 1
Upvotes: 0