HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Merge Sorting in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
sortingpythonmerge

Problem

This my implementation of the Merge Sorting Algorithm:

def merge(series1, series2):
    output = []
    while series1 != [] or series2 != []:
        if series1 == []:
            output.append(series2[0])
            series2.pop(0)
            continue
        if series2 == []:
            output.append(series1[0])
            series1.pop(0)
            continue
        last1 = series1[0]
        last2 = series2[0]
        if last1  1:
        output = []
        length = len(iseries)
        if not is_even(length):
            length -= 1
            for i in range(0, (length-1), 2):
                a = iseries[i]
                b = iseries[i+1]
                output.append(merge(a, b))
            output.append(iseries[-1])
        else:
            for i in range(0, (length-1), 2):
                a = iseries[i]
                b = iseries[i+1]
                output.append(merge(a, b))
        iseries = []
        iseries += output
    return iseries[0]


Basically it splits the items in the initial series into lists of one item (series to iseries). Then I merge the items two-by-two appending the new items to another list (output), and set the main series equals to output. I do this until it's 1 item only and return the 1st item (return iseries[0]).

Solution

In merge you are doing list comparison (series1 != [] or series2 != []). This is expensive. You can avoid this by storing the length of two list beforehand and using that value to detect when to come out of the loop.

Also by using a small trick you can avoid using pop() function.

Avoid using continue. You can easily remove it by putting if else condition properly.

Your variable names are not indicating their actual purpose. It is recommended to use meaning names for variables.

def merge(series1, series2):

output = []
len_series1 = len(series1)
len_series2 = len(series2)
pointer_series1 = 0
pointer_series2 = 0

while pointer_series1 < len_series1 and pointer_series2 < len_series2:
    last1 = series1[pointer_series1] #the variable name is not indicating the actual task of this variable
    last2 = series2[pointer_series2]
    if last1 <= last2:
        output.append(last1)
        pointer_series1 += 1
    elif last2 < last1:
        output.append(last2)
        pointer_series2 += 1

output += series1[pointer_series1:]
output += series2[pointer_series2:]
#the above two statements removes the need to check the emptiness of each list
return output


In is_even function

if x%2== 0


can be rewritten as

if not x%2


The latter one is more 'pythonic'

If I were you I would define a function is_odd instead of is_even, because in the later part of the code you are checking whether a number is odd or not.

merge_sort can also be made more pythonic. The following code actually shows the power of Python to write complicated code in fewer lines:

def merge_sort(series):

iseries = [[i] for i in series]

while len(iseries) > 1:
    iseries = [merge(a,b) if b else a for a,b in map(None,*[iter(iseries)]*2) ]
return iseries[0]

# working explained
#iseries = [[1],[2],[3],[4]]
#iter(iseries) returns an iterable object lets say (o1)
# [iter(iseries)]*2 creates a list [o1,o1]
# map(None,[o1,o1]) calls Identity function; the arguments are o1.next() and o1.next()
# so for the first case Identity() is called on [1] (o1.next()) and [2] (o1.next())

Code Snippets

def merge(series1, series2):

output = []
len_series1 = len(series1)
len_series2 = len(series2)
pointer_series1 = 0
pointer_series2 = 0

while pointer_series1 < len_series1 and pointer_series2 < len_series2:
    last1 = series1[pointer_series1] #the variable name is not indicating the actual task of this variable
    last2 = series2[pointer_series2]
    if last1 <= last2:
        output.append(last1)
        pointer_series1 += 1
    elif last2 < last1:
        output.append(last2)
        pointer_series2 += 1

output += series1[pointer_series1:]
output += series2[pointer_series2:]
#the above two statements removes the need to check the emptiness of each list
return output
def merge_sort(series):

iseries = [[i] for i in series]

while len(iseries) > 1:
    iseries = [merge(a,b) if b else a for a,b in map(None,*[iter(iseries)]*2) ]
return iseries[0]

# working explained
#iseries = [[1],[2],[3],[4]]
#iter(iseries) returns an iterable object lets say (o1)
# [iter(iseries)]*2 creates a list [o1,o1]
# map(None,[o1,o1]) calls Identity function; the arguments are o1.next() and o1.next()
# so for the first case Identity() is called on [1] (o1.next()) and [2] (o1.next())

Context

StackExchange Code Review Q#49777, answer score: 3

Revisions (0)

No revisions yet.