How can I iterate backwards through overlapping pairs of a list?

Question:

I have a list like lst = ["Namaste", "Hello", "Ciao", "Salut"]. I want to iterate over overlapping pairs of values in reverse, printing each pair, to get:

Ciao, Salut
Hello, Ciao
Namaste, Hello

I know that I can use zip(lst, lst[1:]) to iterate forwards. However, if I try simply using reversed on the zip object, to iterate backwards:

lst = ["Namaste", "Hello", "Ciao", "Salut"]

for curr, nxt in reversed(zip(lst, lst[1:])):
    print(f'{curr}, {nxt}')

I get an error message that says TypeError: 'zip' object is not reversible.

How can I achieve my goal?

Asked By: tail

||

Answers:

You can use zip:

l = ["Namaste", "Hello", "Ciao", "Salut"]

for a,b in zip(l[-2::-1], l[::-1]):
    print(f'{a}, {b}')

output:

Ciao, Salut
Hello, Ciao
Namaste, Hello
Answered By: mozway

My code is kinda bulk but it works:

li = ["namaste", "hello", "ciao", "salut",'aymen','khalid']
if len(li)%2 != 0:
    li.append("")
for names in range(0,len(li),2):
    if names%2 == 0:
        print(li[names],li[names+1])
else:
    print(li[names])
Answered By: Motivational Videos

Iterators created by zip cannot be reversed because zip can accept any sort of iterable – including iterators where the iterated elements will be determined on-demand, and might be unlimited. (Recall that in Python, an iterator is a type of iterable.)

Thus, reverse iteration over the inputs isn’t necessarily possible at all; and if it is possible, zip has no way to know "where to start" (for example, given a list iterator, there is no easy way to access the original list, even though the iterator presumably holds a reference internally).

However, if the inputs are known to be reversible, we can simply reverse each before zipping:

>>> lst = ["Namaste", "Hello", "Ciao", "Salut"]
>>> for curr, nxt in zip(reversed(lst[:-1]), reversed(lst)):
...     print(f'{curr}, {nxt}')
... 
Ciao, Salut
Hello, Ciao
Namaste, Hello

Notice the slicing is different from the forwards-iterating version: for the curr iterator we must skip the last element of the list explicitly, since iteration will start at the end, but the next iterator can be made with the original list – we don’t need to trim off the first element of the list, because it won’t pair up. This is the opposite of how it works when iterating forwards.

Similarly, if we are starting with actual sequences, we can create reversed sequences and iterate over those. The simplest way is by slicing, and the simplest way to get "offset" iterators is to slice the offset one twice rather than doing the offset math:

>>> for curr, nxt in zip(lst[::-1][1:], lst[::-1]):
...     print(f'{curr}, {nxt}')
... 
Ciao, Salut
Hello, Ciao
Namaste, Hello

Again, because we iterate in reverse, it’s the first input that needs to be offset.

Answered By: Karl Knechtel
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.