Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect If Item is the Last in a List [duplicate]

I am using Python 3, and trying to detect if an item is the last in a list, but sometimes there will repeats. This is my code:

a = ['hello', 9, 3.14, 9] for item in a:     print(item, end='')     if item != a[-1]:         print(', ') 

And I would like this output:

hello, 9, 3.14, 9 

But I get this output:

hello,  93.14,  9 

I understand why I am getting the output I do not want. I would prefer if I could still use the loop, but I can work around them. (I would like to use this with more complicated code)

like image 369
nedla2004 Avatar asked Oct 01 '16 16:10

nedla2004


People also ask

How do you find the last index of a duplicate element in a list Python?

So the index of last occurrence of an element in original list is equal to (length_of_list - index_in_reversed_list - 1). You can use the list. reverse() method to reverse the list and then find the index of first occurrence of the required element in reversed list by list. index() method.

How do I find the index of a duplicate element in a list?

Method #1 : Using loop + set() In this, we just insert all the elements in set and then compare each element's existence in actual list. If it's the second occurrence or more, then index is added in result list.


2 Answers

While these answers may work for the specific case of the OP, I found they were unsatisfactory for broader application.

Here are the methods I could think of/saw here and their respective timings.

Index Method

urlist_len = len(urlist)-1 for x in urlist:     if urlist.index(x) == urlist_len:         pass 

Negative Slice Method

for x in urlist:     if x == urlist[-1]:         pass 

Enumerate Method

urlist_len = len(urlist)-1 for index, x in enumerate(urlist):     if index == urlist_len:         pass 

Here are some timing for some different methods:

╔════════════════════════════════════════════════════════════════╗ ║                       Timing Results (s)                       ║ ╠═══════════════════════╦════╦═════════╦════════╦═══════╦════════╣ ║ List size             ║ 20 ║ 200     ║ 2000   ║ 20000 ║ 200000 ║ ╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣ ║                       ║ 0  ║ 0.0006  ║ 0.051  ║ 5.2   ║ 560    ║ ║ Index Method          ║    ║         ║        ║       ║        ║ ╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣ ║                       ║ 0  ║ 0       ║ 0.0002 ║ 0.003 ║ 0.034  ║ ║ Negative Slice Method ║    ║         ║        ║       ║        ║ ╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣ ║ Enumerate Method      ║ 0  ║ 0.00004 ║ 0.0005 ║ 0.016 ║ 0.137  ║ ╚═══════════════════════╩════╩═════════╩════════╩═══════╩════════╝ 

Note: values <10us rounded to 0

As you can see, the index method is always slower, and it only get exponentially worse as the list size increases. I don't see any reason to use it ever. The Negative slice method is the fastest in all cases, but if you have duplicate items in your list, it will give you a false positive. Also, the negative slice method requires that the sequence you are iterating over supports indexing. So, in the case of duplicate items in your list (or not index supporting sequence) use the fast-but-not-fastest enumerate method.

Edit: as a commentator noted, calculating the length of the list within the loop isn't ideal. I was able to shave 35% off the enumerate method (not reflected in the table at this moment) using this knowledge.


tldr: use negative slice if all elements are unique objects and sequence supports indexing, otherwise enumerate method

like image 99
Mattwmaster58 Avatar answered Oct 07 '22 14:10

Mattwmaster58


Rather than try and detect if you are at the last item, print the comma and newline when printing the next (which only requires detecting if you are at the first):

a = ['hello', 9, 3.14, 9] for i, item in enumerate(a):     if i:  # print a separator if this isn't the first element         print(',')     print(item, end='') print()  # last newline 

The enumerate() function adds a counter to each element (see What does enumerate mean?), and if i: is true for all values of the counter except 0 (the first element).

Or use print() to insert separators:

print(*a, sep=',\n') 

The sep value is inserted between each argument (*a applies all values in a as separate arguments, see What does ** (double star) and * (star) do for parameters?). This is more efficient than using print(',n'.join(map(str, a))) as this doesn't need to build a whole new string object first.

like image 26
Martijn Pieters Avatar answered Oct 07 '22 12:10

Martijn Pieters