How to Loop Through All But the Last Item of a List

How to loop through all but the last item of a list?

for x in y[:-1]

If y is a generator, then the above will not work.

Loop over list items, except for the last two items (python)

Python lists support slicing like this:

for i in your_list[:-2]

Iterate through Python list and do something on last element

for item in lst:
do_something_to(item)
else:
do_something_extra_special_to_last(item)

Here I just assume that you want to do something extra to the last item (the normal action will still be taken on it beforehand). I also assume you aren't hitting any break statements (in that case else won't execute). Of course, you don't really need else:

for item in lst:
do_something_to(item)
do_something_extra_special_to_last(item)

should work too since the loop variable "leaks" into the enclosing scope and if there are breaks that you're worried about and you really are looping over a sequence, why not:

for item in lst:
do_something_to(item)
do_something_extra_special_to_last(lst[-1])

Python for in loop to print the last item in the list

You are mutating the list whilst iterating over it.

You can use a while loop to do this:

list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

while 'c' in list_A:
print(list_A.pop())

print('job done')

Output:

j
i
h
g
f
e
d
c
job done

A more efficient way would be to determine the index of the first instance of the sentinel character, and remove it and the rest of the list (although the characters are not printed as they are removed):

try:
pos = list_A.index('c')
list_A[:] = list_A[:pos]
# del list_A[pos:] # more efficient alternative suggested by @ShadowRanger
except ValueError as e:
pass

loop is taking only last item

The initialization of total_mass_sum must be outside the for loop in order to prevent reseting of the output payload for each iteration and the append to total_mass_sum must be inside the for loop:

mass_list = [1969,100756]                     
total_mass_sum = []
for a in mass_list:
mass_sum = 0
while a >= 6:
i = (int (a/3)-2)
mass_sum = i+mass_sum
a = i
total_mass_sum.append(mass_sum)

print(total_mass_sum) # output: [966, 50346]

Iterating through all but the last index of an array

One option would be to use dropLast() on the array's indices, allowing you to iterate over a CountableRange of all but the last index of the array.

let names = ["Jim", "Jenny", "Earl"]

for i in names.indices.dropLast() {
print("\(names[i]) loves \(names[i + 1])")
}

If the array has less than two elements, the loop won't be entered.

Another option would be to zip the array with the array where the first element has been dropped, allowing you to iterate through the pairs of elements with their successor elements:

for (nameA, nameB) in zip(names, names.dropFirst()) {
print("\(nameA) loves \(nameB)")
}

This takes advantage of the fact that zip truncates the longer of the two sequences if they aren't of equal length. Therefore if the array has less than two elements, again, the loop won't be entered.

How do I get the last element of a list?

some_list[-1] is the shortest and most Pythonic.

In fact, you can do much more with this syntax. The some_list[-n] syntax gets the nth-to-last element. So some_list[-1] gets the last element, some_list[-2] gets the second to last, etc, all the way down to some_list[-len(some_list)], which gives you the first element.

You can also set list elements in this way. For instance:

>>> some_list = [1, 2, 3]
>>> some_list[-1] = 5 # Set the last element
>>> some_list[-2] = 3 # Set the second to last element
>>> some_list
[1, 3, 5]

Note that getting a list item by index will raise an IndexError if the expected item doesn't exist. This means that some_list[-1] will raise an exception if some_list is empty, because an empty list can't have a last element.

Nested Python for loop only works with the last item in a list

str.split does not accept regular expressions to split on. If you look at the contents of list, you'll see it's just the original string. If you want to split on a regex, you must use the re module:

import re

inp = input("Words: ")
print(inp)
lst = re.split(r'[:,\s]+', inp)
print(lst)

for each in lst:
joined = each + "TEST"
print(joined)

Try it online!

I removed the inner loop because it was doing nothing but multiplying outputs, and renamed variables to avoid name-shadowing built-ins.

What is the pythonic way to detect the last element in a 'for' loop?

Most of the times it is easier (and cheaper) to make the first iteration the special case instead of the last one:

first = True
for data in data_list:
if first:
first = False
else:
between_items()

item()

This will work for any iterable, even for those that have no len():

file = open('/path/to/file')
for line in file:
process_line(line)

# No way of telling if this is the last line!

Apart from that, I don't think there is a generally superior solution as it depends on what you are trying to do. For example, if you are building a string from a list, it's naturally better to use str.join() than using a for loop “with special case”.


Using the same principle but more compact:

for i, line in enumerate(data_list):
if i > 0:
between_items()
item()

Looks familiar, doesn't it? :)


For @ofko, and others who really need to find out if the current value of an iterable without len() is the last one, you will need to look ahead:

def lookahead(iterable):
"""Pass through all values from the given iterable, augmented by the
information if there are more values to come after the current one
(True), or if it is the last value (False).
"""
# Get an iterator and pull the first value.
it = iter(iterable)
last = next(it)
# Run the iterator to exhaustion (starting from the second value).
for val in it:
# Report the *previous* value (more to come).
yield last, True
last = val
# Report the last value.
yield last, False

Then you can use it like this:

>>> for i, has_more in lookahead(range(3)):
... print(i, has_more)
0 True
1 True
2 False

How to take all but the last element in a sequence using LINQ?

I don't know a Linq solution - But you can easily code the algorithm by yourself using generators (yield return).

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> source) {
var it = source.GetEnumerator();
bool hasRemainingItems = false;
bool isFirst = true;
T item = default(T);

do {
hasRemainingItems = it.MoveNext();
if (hasRemainingItems) {
if (!isFirst) yield return item;
item = it.Current;
isFirst = false;
}
} while (hasRemainingItems);
}

static void Main(string[] args) {
var Seq = Enumerable.Range(1, 10);

Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
Console.WriteLine(string.Join(", ", Seq.TakeAllButLast().Select(x => x.ToString()).ToArray()));
}

Or as a generalized solution discarding the last n items (using a queue like suggested in the comments):

public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n) {
var it = source.GetEnumerator();
bool hasRemainingItems = false;
var cache = new Queue<T>(n + 1);

do {
if (hasRemainingItems = it.MoveNext()) {
cache.Enqueue(it.Current);
if (cache.Count > n)
yield return cache.Dequeue();
}
} while (hasRemainingItems);
}

static void Main(string[] args) {
var Seq = Enumerable.Range(1, 4);

Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
Console.WriteLine(string.Join(", ", Seq.SkipLastN(3).Select(x => x.ToString()).ToArray()));
}


Related Topics



Leave a reply



Submit