varnie
varnie

Reputation: 2595

Taking list's tail in a Pythonic way?

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.

Upvotes: 7

Views: 8195

Answers (3)

Eric Platon
Eric Platon

Reputation: 10152

A good old question, and no idea when this was introduced: Unpacking with an asterisk.

>>> t = (1,2,3)
>>> *_, last = t
>>> t
(1, 2, 3)
>>> last
3

And pretty flexible, as the syntax goes beyond the tail:

>>> t = (1,2,3,4)
>>> first, *_, last = t
>>> first
1
>>> last
4
>>> t
(1, 2, 3, 4)

The original post asks for a "Pythonic" way to get the tail. Not sure it is the Python community choice, but it is a syntax rather specific to Python (to the extent of my knowledge).

Upvotes: 1

Nick Dandoulakis
Nick Dandoulakis

Reputation: 43140

Alternative ways,

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


# 2
it = iter(data)
result = next(it) in it

Upvotes: 6

aaronasterling
aaronasterling

Reputation: 71054

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.

Upvotes: 8

Related Questions