473,411 Members | 2,148 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

Last iteration?

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
Oct 12 '07 #1
23 18023
Florian Lindner wrote:
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
Oct 12 '07 #2
Florian Lindner wrote:
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
Oct 12 '07 #3
On Oct 12, 11:58 am, Florian Lindner <Florian.Lind...@xgm.dewrote:
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]

--
Paul Hankin

Oct 12 '07 #4
On Oct 12, 11:58 am, Florian Lindner <Florian.Lind...@xgm.dewrote:
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

Oct 12 '07 #5
On Fri, 2007-10-12 at 12:58 +0200, Florian Lindner wrote:
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

;)

--
Carsten Haese
http://informixdb.sourceforge.net
Oct 12 '07 #6
On Oct 12, 2:18 pm, Carsten Haese <cars...@uniqsys.comwrote:
On Fri, 2007-10-12 at 12:58 +0200, Florian Lindner wrote:
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
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

--
Paul Hankin

Oct 12 '07 #7
Diez B. Roggisch wrote:
Florian Lindner wrote:
>can I determine somehow if the iteration on a list of values is the
last iteration?
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:
>>def mark_last(items):
.... 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
Oct 12 '07 #8
On Oct 12, 12:58 pm, Florian Lindner <Florian.Lind...@xgm.dewrote:
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 :)

Oct 13 '07 #9
On Oct 12, 5:58 am, Florian Lindner <Florian.Lind...@xgm.dewrote:
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

Oct 14 '07 #10
On Oct 14, 8:00 am, Paul McGuire <pt...@austin.rr.comwrote:
On Oct 12, 5:58 am, Florian Lindner <Florian.Lind...@xgm.dewrote:
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
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.

--
Paul Hankin

Oct 14 '07 #11
Peter Otten schrieb:
Diez B. Roggisch wrote:
>Florian Lindner wrote:
>>can I determine somehow if the iteration on a list of values is the
last iteration?
> 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:
>>>def mark_last(items):
... 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
Oct 14 '07 #12
On Oct 14, 5:58 am, Paul Hankin <paul.han...@gmail.comwrote:
On Oct 14, 8:00 am, Paul McGuire <pt...@austin.rr.comwrote:
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.
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
Oct 14 '07 #13
Diez B. Roggisch wrote:
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
Oct 15 '07 #14
Paul Hankin a écrit :
On Oct 12, 11:58 am, Florian Lindner <Florian.Lind...@xgm.dewrote:
>>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 !-)
Oct 16 '07 #15
[Diez B. Roggisch]
out:) But I wanted a general purpose based solution to be available that
doesn't count on len() working on an arbitrary iterable.
[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

Oct 17 '07 #16
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

Oct 17 '07 #17
Raymond Hettinger wrote:
[Diez B. Roggisch]
out:) But I wanted a general purpose based solution to be available that
doesn't count on len() working on an arbitrary iterable.

[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
Oct 17 '07 #18
On Oct 17, 8:16 am, Raymond Hettinger <pyt...@rcn.comwrote:
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)
def lastdetector(iterable):
t, u = tee(iterable)
return izip(chain(imap(lambda x: False, islice(u, 1, None)),
[True]), t)

--
Paul Hankin

Oct 17 '07 #19
[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

Oct 17 '07 #20
"Raymond Hettinger" <pyt...cn.comwrote:
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)
If this is what you call straightforward - heaven forfend
that I ever clap my orbs on something you call convoluted!

:-)

Faced with this problem, I would probably have used
enumerate with a look ahead and the IndexError would
have told me I am at the end...

- Hendrik

Oct 18 '07 #21
On Oct 17, 11:45 pm, Raymond Hettinger <pyt...@rcn.comwrote:
[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.
Perhaps, but I think you'll need a better use-case than this :)

Actually, would a c-version be much faster?

--
Paul Hankin

Oct 18 '07 #22
In article <11*********************@e34g2000pro.googlegroups. com>,
Raymond Hettinger <py****@rcn.comwrote:
[Diez B. Roggisch]
out:) But I wanted a general purpose based solution to be available that
doesn't count on len() working on an arbitrary iterable.

[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: [...]

Although there have already been some nice solutions to this problem,
but I'd like to propose another, which mildly abuses some of the newer
features of Python It is perhaps not as concise as the previous
solutions, nor do I claim it's better; but I thought I'd share it as an
alternative approach.

Before I affront you with implementation details, here's an example:

| from __future__ import with_statement

| with last_of(enumerate(file('/etc/passwd', 'rU'))) as fp:
| for pos, line in fp:
| if fp.marked():
| print "Last line, #%d = %s" % (pos + 1, line.strip())

In short, last_of comprises a trivial context manager that knows how to
iterate over its input, and can also indicate that certain elements are
"marked". In this case, only the last element is marked.

We could also make the truth value of the context manager indicate the
marking, as illustrated here:

| with last_of("alphabet soup") as final:
| for c in final:
| if final:
| print "Last character: %s" % c

This is bit artificial, perhaps, but effective enough. Of course, there
is really no reason you have to use "with," since we don't really care
what happens when the object goes out of scope: You could just as
easily write:

| end = last_of(xrange(25))
| for x in end:
| if end:
| print "Last element: %s" % x

But you could also handle nested context, using "with". Happily, the
machinery to do all this is both simple and easily generalized to other
sorts of "marking" tasks. For example, we could just as well do
something special with all the elements that are accepted by a predicate
function, e.g.,

| def isinteger(obj):
| return isinstance(obj, (int, long))

| with matching(["a", 1, "b", 2, "c"], isinteger) as m:
| for elt in m:
| if m.marked():
| print '#%s' % elt,
| else:
| print '(%s)' % elt,
|
| print

Now that you've seen the examples, here is an implementation. The
"marker" class is an abstract base that does most of the work, with the
"last_of" and "matching" examples implemented as subclasses:

| class marker (object):
| """Generate a trivial context manager that flags certain elements
| in a sequence or iterable.
|
| Usage sample:
| with marker(ITERABLE) as foo:
| for elt in foo:
| if foo.marked():
| print 'this is a marked element'
| else:
| print 'this is an unmarked element'
|
| Subclass overrides:
| .next() -- return the next unconsumed element from the input.
| .marked() -- return True iff the last element returned is marked.
|
| By default, no elements are marked.
| """
| def __init__(self, seq):
| self._seq = iter(seq)
| try:
| self._fst = self._seq.next()
| except StopIteration:
| self.next = self._empty
|
| def _empty(self):
| raise StopIteration
|
| def _iter(self):
| while True:
| yield self.next()
|
| def next(self):
| out = self._fst
| try:
| self._fst = self._seq.next()
| except StopIteration:
| self.next = self._empty
|
| return out
|
| def marked(self):
| return False
|
| def __iter__(self):
| return iter(self._iter())
|
| def __nonzero__(self):
| return self.marked()
|
| def __enter__(self):
| return self
|
| def __exit__(self, *args):
| pass

A bit verbose, but uncomplicated apart from the subtlety in handling the
end case. Here's last_of, implemented as a subclass:

| class last_of (marker):
| def __init__(self, seq):
| super(last_of, self).__init__(seq)
| self._end = False
|
| def next(self):
| out = super(last_of, self).next()
| if self.next == self._empty:
| self._end = True
|
| return out
|
| def marked(self):
| return self._end

And finally, matching:

| class matching (marker):
| def __init__(self, seq, func):
| super(matching, self).__init__(seq)
| self._func = func
| self._mark = False
|
| def next(self):
| out = super(matching, self).next()
| self._mark = self._func(out)
| return out
|
| def marked(self):
| return self._mark

Generally speaking, you should only have to override .next() and
..marked() to make a useful subclass of marker -- and possibly also
__init__ if you need some additional setup.

Cheers,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Oct 19 '07 #23
En Fri, 19 Oct 2007 19:12:49 -0300, Michael J. Fromberger
<Mi******************@Clothing.Dartmouth.EDUescrib ió:
Before I affront you with implementation details, here's an example:

| from __future__ import with_statement

| with last_of(enumerate(file('/etc/passwd', 'rU'))) as fp:
| for pos, line in fp:
| if fp.marked():
| print "Last line, #%d = %s" % (pos + 1, line.strip())

In short, last_of comprises a trivial context manager that knows how to
iterate over its input, and can also indicate that certain elements are
"marked". In this case, only the last element is marked.
The name is very unfortunate. I'd expect that last_of(something) would
return its last element, not an iterator.
Even with a different name, I don't like that marked() (a method of the
iterator) should be related to the current element being iterated.
We could also make the truth value of the context manager indicate the
marking, as illustrated here:

| with last_of("alphabet soup") as final:
| for c in final:
| if final:
| print "Last character: %s" % c

This is bit artificial, perhaps, but effective enough. Of course, there
Again, why should the trueness of final be related to the current element
being iterated?
is really no reason you have to use "with," since we don't really care
what happens when the object goes out of scope: You could just as
easily write:

| end = last_of(xrange(25))
| for x in end:
| if end:
| print "Last element: %s" % x
Again, why the truth value of "end" is related to the current "x" element?
But you could also handle nested context, using "with". Happily, the
machinery to do all this is both simple and easily generalized to other
sorts of "marking" tasks. For example, we could just as well do
something special with all the elements that are accepted by a predicate
function, e.g.,

| def isinteger(obj):
| return isinstance(obj, (int, long))

| with matching(["a", 1, "b", 2, "c"], isinteger) as m:
| for elt in m:
| if m.marked():
| print '#%s' % elt,
| else:
| print '(%s)' % elt,
|
| print
I think you are abusing context managers *a*lot*!
Even accepting such evil thing as matching(...), the above code could be
equally written as:

m = matching(...)
for elt in m:
...

Anyway, a simple generator that yields (elt, function(elt)) would be
enough...

--
Gabriel Genellina

Oct 20 '07 #24

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: Raymond Hettinger | last post by:
Here is a discussion draft of a potential PEP. The ideas grew out of the discussion on pep-284. Comments are invited. Dart throwing is optional. Raymond Hettinger ...
2
by: Abdullah Khaidar | last post by:
Is there any iteration style we must use to get faster processing time? I've tried with some style to concat number in list. But I still don't know which one is the recommended style. >>> def...
32
by: James Curran | last post by:
I'd like to make the following proposal for a new feature for the C# language. I have no connection with the C# team at Microsoft. I'm posting it here to gather input to refine it, in an "open...
0
by: bunty.gopal | last post by:
I am trying to use the PreparedStatement's addBatch to load data in an ETL-like process into a table. There is a single prepared statement. The parameters are set on it and prepStmt.addBatch() is...
75
by: Sathyaish | last post by:
Can every problem that has an iterative solution also be expressed in terms of a recursive solution? I tried one example, and am in the process of trying out more examples, increasing their...
5
by: Denis Petronenko | last post by:
Hello, for(int i=0; i<100; ++i){ cout << i << ","; } // how can i remove last comma here? ...... cout << endl;
0
by: danikdanik | last post by:
Hello all, The folowing code below returns the same last access time of the tty i am writing to for every loop iteration, what just can't be true. What am I doing wrong? Is there any other way to...
1
by: bunty.gopal | last post by:
This is the solution to the issue in the subject, question itself was posted in a previous thread long back. Use the latest DB2 db2cc.jar fixpack on the client, or add "deferPrepares=false" to...
3
by: Ilkka Maatta | last post by:
PHP code ..... <? //Open file. $file=fopen("file.txt","r"); //read file so long when it isn't end. while (!feof($file)) { //read and print row + LF. $rivi=fgets($file,1024);
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.