tail
tail

Reputation: 411

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

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?

Upvotes: 0

Views: 600

Answers (6)

slothrop
slothrop

Reputation: 5418

In Python 3.10 and up, this can be done concisely using itertools.pairwise on the reversed iterator of the list. We just need to remember to also reverse the order of each yielded pair, so that it returns to the "forward" direction:

from itertools import pairwise

lst = ["Namaste", "Hello", "Ciao", "Salut"]
for i, j in pairwise(reversed(lst)):
    print(f"{j}, {i}")

Output:

Ciao, Salut
Hello, Ciao
Namaste, Hello

Upvotes: 0

aiootp
aiootp

Reputation: 156

How can I achieve my goal?

Here's a solution that doesn't make unnecessary copies of lists:

>>> def reverse_pairwise_reader(sequence):
...     for i in range(-1, -len(sequence), -1):
...         yield sequence[i - 1], sequence[i]
...     yield sequence[-1], sequence[0]
...
>>> [*reverse_pairwise_reader(lst)]
... [('Ciao', 'Salut'),
     ('Hello', 'Ciao'),
     ('Namaste', 'Hello'),
     ('Salut', 'Namaste')]

This could save a substantial amount of memory, depending on how big your lists are.

Upvotes: 0

shaoyl85
shaoyl85

Reputation: 1964

For reversing zip, this works,

for i, j in zip(*map(reversed, (list1, list2))):
    ...

Upvotes: 1

Karl Knechtel
Karl Knechtel

Reputation: 61498

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.

Upvotes: 0

Motivational Videos
Motivational Videos

Reputation: 1

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])

Upvotes: 0

mozway
mozway

Reputation: 260410

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

Upvotes: 3

Related Questions