tags:

views:

111

answers:

2

Hi. Suppose we have:

from random import randrange
data = [(randrange(8), randrange(8)) for x in range(8)]

And we have to test if the first item equals to one of a tail. I am curious, how we would do it in most simple way without copying tail items to the new list? Please take into account this piece of code gets executed many times in, say, update() method, and therefore it has to be quick as possible.

Using an additional list (unnesessary memory wasting, i guess):

head = data[0]
result = head in data[1:]

Okay, here's another way (too lengthy):

i = 1
while i < len(data):
    result = head == data[i]
    if result:
        break
    i+=1

What is the most Pythonic way to solve this? Thanks.

+4  A: 

Nick D's Answer is better

use islice. It doesn't make a copy of the list and essentially embeds your second (elegant but verbose) solution in a C module.

import itertools

head = data[0]
result = head in itertools.islice(data, 1, None)

for a demo:

>>> a = [1, 2, 3, 1]
>>> head = a[0]
>>> tail = itertools.islice(a, 1, None)
>>> head in tail
True

Note that you can only traverse it once but if all you want to do is check that the head is or is not in the tail and you're worried about memory, then I think that this is the best bet.

aaronasterling
Thank you! backing to previous comment, is it true that "data[0] in data[1:]" doesn't create new copy of list?
varnie
Cool, I didn't realize you could use `in` on iterators. It should be `itertools.islice(data, 1, None)` though — otherwise it will `StopIteration` after the 0th element.
intuited
@intuited, good looking out. I made the mistake when making the demo and edited the wrong line out. @varnie, anytime. I'm not sure. See my response to that comment. I'm dubious and want to see documentation. I've never heard of it but I'm a bit of a newb.
aaronasterling
@varnie. You should accept Nick D's answer so I can delete this one. He has better solutions.
aaronasterling
@AaronMcSmooth: Done. But in any case i found your solution being useful too.
varnie
@AaronMcSmooth: I think you should keep this answer, it's a useful alternative. I actually prefer it, because it's a one-liner (assuming you have already imported `itertools`) and doesn't waste effort by iterating past the desired value as does `count`. It's also good for people to know about because it's more generalized.
intuited
+4  A: 

Alternative ways,

# 1
result = data.count(data[0]) > 1


# 2
it = iter(data)
it.next()
result = data[0] in it
Nick D