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]