Posted: Thu Jan 24, 2008 10:19 am Post subject: Lists - returning all occurences of value
Is there a way to return the position of all occurrences of a certain value in a list. I know there is a built in list function index() which returns the position of the first occurrence of a given value, but I need to know the position of all occurrences.
Sponsor Sponsor
Nick
Posted: Thu Jan 24, 2008 11:14 am Post subject: RE:Lists - returning all occurences of value
well couldn't you just print your list to see all values?
wtd
Posted: Thu Jan 24, 2008 12:44 pm Post subject: RE:Lists - returning all occurences of value
As far as I know there is no built-in method to do this, but it's all of two concise lines of code to define it yourself.
code:
def all_indexes(lst, f):
return (i for i, x in enumerate(lst) if f(x))
a = [1, 2, 3, 4, 3, 2, 1]
print list(all_indexes(a, lambda x: x == 1))
Outputs:
code:
[0, 6]
mike200015
Posted: Thu Jan 24, 2008 1:07 pm Post subject: Re: Lists - returning all occurences of value
yea that would work great! thanks wtd
wtd
Posted: Thu Jan 24, 2008 2:42 pm Post subject: RE:Lists - returning all occurences of value
It's worth asking... do you understand how the code I posted works?
mike200015
Posted: Thu Jan 24, 2008 3:10 pm Post subject: Re: Lists - returning all occurences of value
yea i do after looking over it for a few mins... the only confusing part that i'm not 100% on is the return statement.. looks confusing since its on a single line. I understand what is being returned, just not clear on how it works as a single line
wtd
Posted: Thu Jan 24, 2008 4:05 pm Post subject: RE:Lists - returning all occurences of value
The function is returning a generator object, which is created by the generator expression:
code:
i for i, x in enumerate(lst) if f(x)
Understanding how this works is the key to understanding the magic of this function.
Note that the enumerate function also returns a generator object.
In earlier version of Python we had list comprehensions, and they were good.
Let's say you have a list:
code:
my_list = [1, 4, 3, 2]
You can transform that into another list like so:
code:
my_other_list = [x * 2 for x in my_list]
At which point you'd have:
code:
[2, 8, 6, 4]
And you can tack on conditionals.
code:
my_other_list = [x * 2 for x in my_list if x * 2 <= 6]
From which you get:
code:
[2, 6, 4]
Now, what's the problem with list comprehensions? Well, let's say I have a list "my_list" with one million values in it. That's a big list, and it takes a lot of memory.
Now, let's say I want to iterate over a transformation of that list.
code:
for x in [(x * 2 - 1) / 3 for x in my_list]:
print x
The list comprehension generates the entire new list before it even begins iterating. Now I have two huge lists in memory, and a lot of computation going on before I even begin to do anything useful with that data.
What if I leave the loop early?
code:
for x in [(x * 2 - 1) / 3 for x in my_list]:
print x
if x == 42:
break
That might break after the first run of the loop. That means I've done a whole lot of computation, and used a whole lot of memory for nothing.
This is not ideal.
Generator objects and expressions fix this by introducing a sort of laziness. Rather than generating an entirely new list in its entirety, we simply have an object that when a certain method is called, will give the program its next value. If we only ask it for one value, then it only does that much work.
Does this make sense? Don't worry if it doesn't at first. Python is an enormously powerful programming language, and it can break even strong minds.
mike200015
Posted: Thu Jan 24, 2008 4:24 pm Post subject: Re: Lists - returning all occurences of value
That makes sense, but the list comprehension looks the same as the generator object/expression. What would the list comprehension example you showed look like as a generator object/expression ?
Sponsor Sponsor
wtd
Posted: Thu Jan 24, 2008 4:29 pm Post subject: RE:Lists - returning all occurences of value
It'd look like:
code:
for x in ((x * 2 - 1) / 3 for x in my_list):
print x
if x == 42:
break
mike200015
Posted: Thu Jan 24, 2008 4:36 pm Post subject: Re: Lists - returning all occurences of value
hmm.. a little confused lol
wtd
Posted: Thu Jan 24, 2008 5:26 pm Post subject: RE:Lists - returning all occurences of value
Note that the square brackets got replaced with parentheses. The syntactic similarity was intentional on the part of the language designers.
mike200015
Posted: Fri Jan 25, 2008 1:58 pm Post subject: Re: Lists - returning all occurences of value
I didnt notice that. So thats the difference between making a list comprehension and a generator expression?
McKenzie
Posted: Fri Jan 25, 2008 8:20 pm Post subject: Re: Lists - returning all occurences of value
The most important thing is that you understand your own code. If you find what wtd posted to be a little to dense try a more imperative approach like:
Python:
def findAll(lst, val):
ans = [] for i inrange(len(lst)):
if lst[i] == val:
ans.append(i) return ans
Posted: Sat Jan 26, 2008 1:20 am Post subject: Re: Lists - returning all occurences of value
Just for fun, let's slowly morph that:
code:
def findAll(lst, val):
ans = []
for i in range(len(lst)):
if lst[i] == val:
ans.append(i)
return ans
Becomes:
code:
def findAll(lst, val):
ans = [i for i in range(len(lst)) if lst[i] == val]
return ans
Becomes:
code:
def findAll(lst, val):
return [i for i in range(len(lst)) if lst[i] == val]
Now, consider:
code:
>>> lst = [3, 5, 2]
>>> for i in range(len(lst)):
... print i, lst[i]
...
0 3
1 5
2 2
>>> for i, x in enumerate(lst):
... print i, x
...
0 3
1 5
2 2
>>>
So, we can now...
code:
def findAll(lst, val):
return [i for i, x in enumerate(lst) if x == val]
shaon
Posted: Thu Jan 31, 2008 7:49 pm Post subject: Re: Lists - returning all occurences of value
how come you used enumerate over for i in range(....), is enumerate more efficient or is just for less typing?