tags:

views:

157

answers:

4

I need to do some special operation for the last element in a list. Is there any better way than this?

array = [1,2,3,4,5] 
for i, val in enumerate(array): 
  if (i+1) == len(array): 
    // Process for the last element 
  else: 
    // Process for the other element 
+8  A: 
for item in list[:-1]:
    print "Not last: ", item
print "Last: ", list[-1]

If you don't want to make a copy of list, you can make a simple generator:

# itr is short for "iterable" and can be any sequence, iterator, or generator

def notlast(itr):
    itr = iter(itr)  # ensure we have an iterator
    prev = itr.next()
    for item in itr:
        yield prev
        prev = item

# lst is short for "list" and does not shadow the built-in list()
# 'L' is also commonly used for a random list name
lst = range(4)
for x in notlast(lst):
    print "Not last: ", x
print "Last: ", lst[-1]

Another definition for notlast:

import itertools
notlast = lambda lst:itertools.islice(lst, 0, len(lst)-1)
liori
I advise you against using `list` and `iter` as variable names as they shadow the builtins
gnibbler
I gave you +1, but the code you had there for the iterator case didn't work. I'm going to go in and fix it now.
steveha
A simpler version of your first definition of notlast: def butlast(xs): prev = xs.next() for x in xs: yield prev prev = x(I'd also add a first line: xs = iter(xs))
Darius Bacon
I guess I can't format Python code in a comment. Oh, well.
Darius Bacon
Following steveha's example, I went ahead and edited my suggestion in. I'm not sure that was really the polite thing to do -- hope you don't mind.
Darius Bacon
@Darius: I'm glad you did it. I don't sit on SO 24h/day, and if OP gets best answer possible, that's good thing.
liori
+4  A: 

If your sequence isn't terribly long then you can just slice it:

for val in array[:-1]:
  do_something(val)
else:
  do_something_else(array[-1])
Ignacio Vazquez-Abrams
+1 for "for/else", but note that if the "do something" code actually involves a break statement (early termination of the loop) then the else code would be skipped. Whether that's relevant in this case is up to the OP, but it should be noted.
Peter Hansen
Another +1 for `for/else`
jeffjose
+1  A: 

using itertools

>>> from itertools import repeat, chain,izip
>>> for val,special in izip(array, chain(repeat(False,len(array)-1),[True])):
...     print val, special
... 
1 False
2 False
3 False
4 False
5 True

Version of liori's answer to work on any iterable (doesn't require len() or slicing)

def last_flagged(seq):
    seq = iter(seq)
    a = next(seq)
    for b in seq:
        yield a, False
        a = b
    yield a, True        

mylist = [1,2,3,4,5]
for item,is_last in last_flagged(mylist):
    if is_last:
        print "Last: ", item
    else:
        print "Not last: ", item
gnibbler
A: 
for i in len(myList):
    if i==len(myList)-1:
        print "The last item is:", myList[i]
    else:
        print "Not last item:", myList[i]
inspectorG4dget
If you **must** use this particular i-construct (unpythonic imo) , why not use `for i, e in enumerate(myList)`?
ChristopheD
I just never got too friendly with enumerate (I was never made aware of its existence when I was first taught Python). Personally, I'm trying to get more familiar with it.
inspectorG4dget
Sorry, but I'm very tempted to give you a -1 on this. This is non-Pythonic. Even the `enumerate()` version is not recommended. This will work, but it's so ugly. I especially hate that you tested for `==` so that the "last item" case is *first*. The accepted answer really is the best way to do this in Python.
steveha