Home > Enterprise >  How to loop over all elements of different sorted lists in sorted order?
How to loop over all elements of different sorted lists in sorted order?

Time:01-22

I have several sorted lists. How can I loop over all elements in sorted order efficiently and elegantly? In my real-life problem, those lists contain elements that are directly comparable and sortable but are different and require different treatment.

I prefer to retain my lists, which is why I copy them manually. If that is missing from a one-liner solution like a library function, I will gladly use that and copy the lists beforehand.
This code does what I want but is neither efficient nor elegant.

from random import randint

a: list = []
b: list = []
c: list = []

list_of_lists: list = [a, b, c]

for i in range(10):
    l = randint(0, 2)
    list_of_lists[l].append(i)

print(a, b, c)
a_copy = a.copy()
b_copy = b.copy()
c_copy = c.copy()

# print the elements of the lists in sorted order
x = a_copy.pop(0)
y = b_copy.pop(0)
z = c_copy.pop(0)

while (x and x is not 1000) or \
        (y and y is not 1000) or \
        (z and z is not 1000):
    if x is not 1000 and x < y and x < z:
        print(x)
        if a_copy and a_copy[0]:
            x=a_copy.pop(0)
        else:
            x = 1000
    elif y is not 1000 and y < x and y < z:
        print(y)
        if b_copy and b_copy[0]:
            y=b_copy.pop(0)
        else:
            y = 1000
    elif z is not 1000 and z < x and z < y:
        print(z)
        if c_copy and c_copy[0]:
            z=c_copy.pop(0)
        else:
            z = 1000

CodePudding user response:

The heapq module provides a function to merge sorted iterables into a single sorted iterator.

from heapq import merge

merged = list(merge(a, b, c))

For example,

>>> a, b, c
([1, 4, 7], [2, 5, 8], [3, 6, 9])
>>> from heapq import merge
>>> list(merge(a, b, c))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> (a, b, c)
([1, 4, 7], [2, 5, 8], [3, 6, 9])

CodePudding user response:

In Python, easiest and quite efficient is to actually just concatenate the list and sort them.

l = [*a, *b, *c] # alternatively, list(chain.from_iterable(list_of_lists))
l.sort()

In theory, this would be O(n*log(n)), but Python list.sort() uses a clever sort algorithm called timsort, which are designed to take advantage of runs in the data, such that it would sort a "mostly already sorted lists" -- such as concatenation of multiple sorted lists -- much faster than theory.

CodePudding user response:

Combine them into a single list, and then sort that.

You can use a nested comprehension to flatten the lists as you iterate over them:

>>> a, b, c = [2, 4, 3], [1, 7, 5], [9, 6, 8]
>>> sorted(i for x in (a, b, c) for i in x)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

or you can just add the lists together:

>>> sorted(a   b   c)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
  • Related