Combining two sorted lists in Python
People seem to be over complicating this.. Just combine the two lists, then sort them:
>>> l1 = [1, 3, 4, 7]
>>> l2 = [0, 2, 5, 6, 8, 9]
>>> l1.extend(l2)
>>> sorted(l1)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
..or shorter (and without modifying l1
):
>>> sorted(l1 + l2)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
..easy! Plus, it's using only two built-in functions, so assuming the lists are of a reasonable size, it should be quicker than implementing the sorting/merging in a loop. More importantly, the above is much less code, and very readable.
If your lists are large (over a few hundred thousand, I would guess), it may be quicker to use an alternative/custom sorting method, but there are likely other optimisations to be made first (e.g not storing millions of datetime
objects)
Using the timeit.Timer().repeat()
(which repeats the functions 1000000 times), I loosely benchmarked it against ghoseb's solution, and sorted(l1+l2)
is substantially quicker:
merge_sorted_lists
took..
[9.7439379692077637, 9.8844599723815918, 9.552299976348877]
sorted(l1+l2)
took..
[2.860386848449707, 2.7589840888977051, 2.7682540416717529]
Merging two sorted python lists
You can use heapq.merge
for this. It takes multiple sorted iterables and merges them into a single sorted output, so:
c = list(heapq.merge(
sorted(a, reverse=True),
sorted(b, reverse=True),
reverse=True)
Note that this works also with iterables (e.g. lazily-calculated, potentially consumable objects), which is when you are more likely to use it (when combining sorted iterables).
I am assuming you get the lists pre-sorted or you just want to know how to do this, since it would probably be preferable to merge the lists first and then sort them (either with sorted
or mutating them with .sort()
).
How do I concatenate two lists in Python?
Use the +
operator to combine the lists:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = listone + listtwo
Output:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
Efficient solution for merging 2 sorted lists in Python
Its because of the Python implementation of .sort()
. Python uses something called Timsort.
Timsort is a type of mergesort. Its distinguishing characteristic is that it identifies "runs" of presorted data that it uses for the merge. In real world data, sorted runs in unsorted data are very common and you can sort two sorted arrays in O(n) time if they are presorted. This can cut down tremendously on sort times which typically run in O(nlog(n)) time.
So what's happening is that when you call list.sort()
in Python, it identifies the two runs of sorted data list1
and list2
and merges them in O(n) time. Additionally, this implementation is compiled C code which will be faster than an interpreted Python implementation doing the same thing.
Merge two sorted lists and preserve order
You might want to use to use topological sorting. If you don't want to implement the algorithm from scratch, you can use the NetworkX Python package:
from itertools import chain
from networkx import DiGraph, topological_sort
l1 = ["A", "D", "B", "C"]
l2 = ["X", "A", "Y", "B"]
# Build the graph
G = DiGraph(chain(zip(l1[:-1], l1[1:]), zip(l2[:-1], l2[1:])))
# Return a list of nodes in topological sort order
result = list(topological_sort(G))
# result: ['X', 'A', 'Y', 'D', 'B', 'C']
Basically, you build a graph where every directed edge from vertex u to vertex v implies that u comes before v in the ordering. In this specific example, "A" comes before "D", "D" comes before "B" etc:
>>> G.edges
[('A', 'D'), ('A', 'Y'), ('D', 'B'), ('B', 'C'), ('X', 'A'), ('Y', 'B')]
Merging two sorted lists into a larger sorted list
Make sure you keep adding elements even if a list is out of elements. Your current code stops once either aList
or bList
is empty, which is probably not what you want.
You can do this by using the fact that an empty list is evaluated as False
using an if
expression:
def merge(aList, bList):
newList = []
while (aList or bList): # single empty list won't stop the loop
if not bList or (aList and aList[0] < bList[0]):
# either bList is empty, or aList has next item
newList.append(aList.pop(0))
else:
# bList has next item
newList.append(bList.pop(0))
reutrn newList
list1 = [3, 4, 8, 9]
list2 = [1, 2, 5, 8]
print(merge(list1, list2))
print(list1)
print(list2)
Output:
sh-4.2# python3 main.py
[1, 2, 3, 4, 5, 8, 8, 9]
[]
[]
Merging two sorted lists into one in descending order
You just have to do everything in the opposite way--retrieve items from the tail instead of the head, go for the larger of the two when making comparisons, and return the remaining list in reverse order when the other is exhausted:
def merge(lst1, lst2):
if not lst1:
return lst2[::-1]
if not lst2:
return lst1[::-1]
if lst1[-1] < lst2[-1]:
return [lst2[-1]] + merge(lst1, lst2[:-1])
else:
return [lst1[-1]] + merge(lst1[:-1], lst2)
so that:
merge([2,5,9,12], [0,1,3,4,8])
would return:
[12, 9, 8, 5, 4, 3, 2, 1, 0]
Related Topics
What Are the Most Common Python Docstring Formats
Insert a Row to Pandas Dataframe
How to Get First Element in a List of Tuples
How to Make a Scatter Plot Colored by Density in Matplotlib
Python Socket Receive Large Amount of Data
Scipy.Misc Module Has No Attribute Imread
How Does Functools Partial Do What It Does
How to Read the Rgb Value of a Given Pixel in Python
How to Find the Last Occurrence of an Item in a Python List
What Is the Easiest Way to Remove All Packages Installed by Pip
Importing an Ipynb File from Another Ipynb File
Calling Class Staticmethod Within the Class Body
Why Does Assigning to My Global Variables Not Work in Python