Last iteration?

F

Florian Lindner

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9


Can this be acomplished somehow?

Thanks,

Florian
 
S

Stefan Behnel

Florian said:
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9


Can this be acomplished somehow?

You could do this:

l = [1,2,3]
s = len(l) - 1
for i, item in enumerate(l): # Py 2.4
if i == s:
print item*item
else:
print item

Or, you could look one step ahead:

l = [1,2,3]
next = l[0]
for item in l[1:]:
print next
next = item
print next * next

Stefan
 
D

Diez B. Roggisch

Florian said:
Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9


Can this be acomplished somehow?

def last_iter(iterable):
it = iter(iterable)
buffer = [it.next()]
for i in it:
buffer.append(i)
old, buffer = buffer[0], buffer[1:]
yield False, old
yield True, buffer[0]



for last, i in last_iter(xrange(4)):
if last:
print i*i
else:
print i



Diez
 
P

Paul Hankin

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

Yes, either use enumerate or just stop the loop early and deal with
the last element outside the loop.

xs = [1, 2, 3]
for x in xs[:-1]:
print x
print xs[-1] * xs[-1]
 
T

tasjaevan

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9

Can this be acomplished somehow?

Another suggestion:

l = [1, 2, 3]
for i in l[:-1]: print i
i = l[-1]
print i*i


James
 
C

Carsten Haese

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9

Here's another solution:

mylist = [1,2,3]
for j,i in reversed(list(enumerate(reversed(mylist)))):
if j==0:
print i*i
else:
print i

;)
 
P

Paul Hankin

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i
that would print

Here's another solution:

mylist = [1,2,3]
for j,i in reversed(list(enumerate(reversed(mylist)))):
if j==0:
print i*i
else:
print i

Nice! A more 'readable' version is:

mylist = [1,2,3]
for not_last, i in reversed(list(enumerate(reversed(mylist)))):
if not_last:
print i
else:
print i * i
 
P

Peter Otten

Diez said:
Florian Lindner wrote:
def last_iter(iterable):
it = iter(iterable)
buffer = [it.next()]
for i in it:
buffer.append(i)
old, buffer = buffer[0], buffer[1:]
yield False, old
yield True, buffer[0]

This can be simplified a bit since you never have to remember more than on
item:
.... items = iter(items)
.... last = items.next()
.... for item in items:
.... yield False, last
.... last = item
.... yield True, last
....
list(mark_last([])) []
list(mark_last([1])) [(True, 1)]
list(mark_last([1,2]))
[(False, 1), (True, 2)]

Peter
 
?

=?iso-8859-1?q?Robin_K=E5veland?=

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9

Can this be acomplished somehow?

Thanks,

Florian


If you want to do this over a list or a string, I'd just do:

for element in iterable[:-1]: print iterable
print iterable[-1] * iterable[-1]

No need for it to get more advanced than that :)
 
P

Paul McGuire

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i

that would print

1
2
9

Can this be acomplished somehow?

Thanks,

Florian

Maybe it's a leftover from my C++ days, but I find the iteration-based
solutions the most appealing. This is a refinement of the previous
post by Diez Roggisch. The test method seems to match your desired
idiom pretty closely:

def signal_last(lst):
last2 = None
it = iter(lst)
try:
last = it.next()
except StopIteration:
last = None
for last2 in it:
yield False, last
last = last2
yield True, last

def test(t):
for isLast, item in signal_last(t):
if isLast:
print "...and the last item is", item
else:
print item

test("ABC")
test([])
test([1,2,3])

Prints:

A
B
....and the last item is C
....and the last item is None
1
2
....and the last item is 3

-- Paul
 
P

Paul Hankin

Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i
that would print

Can this be acomplished somehow?

Florian

Maybe it's a leftover from my C++ days, but I find the iteration-based
solutions the most appealing. This is a refinement of the previous
post by Diez Roggisch. The test method seems to match your desired
idiom pretty closely:

def signal_last(lst):
last2 = None
it = iter(lst)
try:
last = it.next()
except StopIteration:
last = None
for last2 in it:
yield False, last
last = last2
yield True, last

This yields a value when the iterator is empty, which Diez's solution
didn't. Logically, there is no 'last' element in an empty sequence,
and it's obscure to add one. Peter Otten's improvement to Diez's code
looks the best to me: simple, readable and correct.
 
D

Diez B. Roggisch

Peter said:
Diez said:
Florian Lindner wrote:
def last_iter(iterable):
it = iter(iterable)
buffer = [it.next()]
for i in it:
buffer.append(i)
old, buffer = buffer[0], buffer[1:]
yield False, old
yield True, buffer[0]

This can be simplified a bit since you never have to remember more than on
item:
... items = iter(items)
... last = items.next()
... for item in items:
... yield False, last
... last = item
... yield True, last
...
list(mark_last([])) []
list(mark_last([1])) [(True, 1)]
list(mark_last([1,2]))
[(False, 1), (True, 2)]

Nice.

I tried to come up with that solution in the first place - but most
probably due to an java-coding induced brain overload it didn't work
out:) But I wanted a general purpose based solution to be available that
doesn't count on len() working on an arbitrary iterable.

Diez
 
P

Paul McGuire

This yields a value when the iterator is empty, which Diez's solution
didn't. Logically, there is no 'last' element in an empty sequence,
and it's obscure to add one. Peter Otten's improvement to Diez's code
looks the best to me: simple, readable and correct.

Of course! For some reason I thought I was improving Peter Otten's
version, but when I modified my submission to behave as you stated, I
ended right back with what Peter had submitted. Agreed - nice and
neat!

-- Paul
 
P

Peter Otten

Diez said:
out:) But I wanted a general purpose based solution to be available that
doesn't count on len() working on an arbitrary iterable.

You show signs of a severe case of morbus itertools.
I, too, am affected and have not yet fully recovered...

Peter
 
B

Bruno Desthuilliers

Paul Hankin a écrit :
Hello,
can I determine somehow if the iteration on a list of values is the last
iteration?

Example:

for i in [1, 2, 3]:
if last_iteration:
print i*i
else:
print i


Yes, either use enumerate or just stop the loop early and deal with
the last element outside the loop.

xs = [1, 2, 3]
for x in xs[:-1]:
print x
print xs[-1] * xs[-1]

At least something sensible !-)
 
R

Raymond Hettinger

[Diez B. Roggisch]
[Peter Otten]
You show signs of a severe case of morbus itertools.
I, too, am affected and have not yet fully recovered...

Maybe you guys were secretly yearning for a magical last element
detector used like this:

for islast, value in lastdetecter([1,2,3]):
if islast:
print 'Last', value
else:
print value

Perhaps it could be written plainly using generators:

def lastdetecter(iterable):
it = iter(iterable)
value = it.next()
for nextvalue in it:
yield (False, value)
value = nextvalue
yield (True, value)

Or for those affected by "morbus itertools", a more arcane incantation
would be preferred:

from itertools import tee, chain, izip, imap
from operator import itemgetter

def lastdetecter(iterable):
"fast iterator algebra"
lookahead, t = tee(iterable)
lookahead.next()
t = iter(t)
return chain(izip(repeat(False), imap(itemgetter(1),
izip(lookahead, t))), izip(repeat(True),t))


Raymond
 
R

Raymond Hettinger

def lastdetecter(iterable):
"fast iterator algebra"
lookahead, t = tee(iterable)
lookahead.next()
t = iter(t)
return chain(izip(repeat(False), imap(itemgetter(1),
izip(lookahead, t))), izip(repeat(True),t))

More straight-forward version:

def lastdetecter(iterable):
t, lookahead = tee(iterable)
lookahead.next()
return izip(chain(imap(itemgetter(0), izip(repeat(False),
lookahead)), repeat(True)), t)


Raymond
 
P

Peter Otten

Raymond said:
[Diez B. Roggisch]
[Peter Otten]
You show signs of a severe case of morbus itertools.
I, too, am affected and have not yet fully recovered...

Maybe you guys were secretly yearning for a magical last element
detector used like this:

Not secretly...
def lastdetecter(iterable):
it = iter(iterable)
value = it.next()
for nextvalue in it:
yield (False, value)
value = nextvalue
yield (True, value)

as that's what I posted above...
def lastdetecter(iterable):
"fast iterator algebra"
lookahead, t = tee(iterable)

# make it cope with zero-length iterables
lookahead = islice(lookahead, 1, None)
return chain(izip(repeat(False), imap(itemgetter(1),
izip(lookahead, t))), izip(repeat(True),t))

and that's the "somebody call the doctor -- now!" version ;)

Peter
 
P

Paul Hankin

More straight-forward version:

def lastdetecter(iterable):
t, lookahead = tee(iterable)
lookahead.next()
return izip(chain(imap(itemgetter(0), izip(repeat(False),
lookahead)), repeat(True)), t)

def lastdetector(iterable):
t, u = tee(iterable)
return izip(chain(imap(lambda x: False, islice(u, 1, None)),
[True]), t)
 
R

Raymond Hettinger

[Paul Hankin]
def lastdetector(iterable):
t, u = tee(iterable)
return izip(chain(imap(lambda x: False, islice(u, 1, None)),
[True]), t)

Sweet! Nice, clean piece of iterator algebra.

We need a C-speed verion of the lambda function, something like a K
combinator that consumes arguments and emits constants.


Raymond
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top