3
\$\begingroup\$

I am re-learning my fundamental algorithms and have been told my Python is overly verbose.
Can you take a look at my merge sort algorithm and let me know how you would clean it up and make it morepythonic, if applicable?

def merge(left,right):    out = []    l_rest = []    i = left[0]    while i is not None:        if right:            if i < right[0]:                out.append(i)                left.remove(i)            else:                out.append(right[0])                right.remove(right[0])        else:            out.append(i)            left.remove(i)                 if len(left) > 0:             i = left[0]         else:             i = None    for i in l_rest:        out.append(i)    for i in right:        out.append(i)    return outdef sort(lst):    if len(lst) == 1:        return lst         left = sort(lst[:len(lst)//2])    right = sort(lst[len(lst)//2:])    return merge(left,right)
toolic's user avatar
toolic
16.4k6 gold badges29 silver badges221 bronze badges
askedApr 4, 2018 at 14:03
Chris's user avatar
\$\endgroup\$
6
  • \$\begingroup\$Your code seems to have a bug: it doesn't include the pivot in the result.\$\endgroup\$CommentedApr 4, 2018 at 16:18
  • \$\begingroup\$@SolomonUcko Thanks, not sure I follow, but I will debug tonight.\$\endgroup\$CommentedApr 4, 2018 at 16:49
  • \$\begingroup\$Sorry, at first I thought it was quicksort. What I meant was that, for example, if I sort a list of the numbers 0-99, repeated 100 times, then shuffled, the 0s are missing.\$\endgroup\$CommentedApr 4, 2018 at 17:01
  • 1
    \$\begingroup\$why not justout += l_rest + right instead offor i in l_rest: out.append(i); for i in right: out.append(i)\$\endgroup\$CommentedApr 4, 2018 at 18:21
  • \$\begingroup\$@SolomonUcko fixed, that was nasty. Thanks. I chose to fix that and not fix YuliaV's suggestion inline... Not sure the best practice for implementing incremental improvements, but I like their idea.\$\endgroup\$CommentedApr 5, 2018 at 5:01

2 Answers2

2
\$\begingroup\$

Indentation

I get a syntax error on my version of Python due to the indentationof these lines:

    if len(left) > 0:        i = left[0]    else:        i = None

I had to move them one space to the left to fix the error. Perhapsyour version of Python is more forgiving, or perhaps there was aproblem when you pasted the code into the question.

Naming

sort is the name of a built-in list method. It would be better to renameyour function:

def sort(lst):

to something like:

def merge_sort(lst):

It is common to use a plural noun for an array variable name.For example,lst could beitems, or something more specificto this application.

The same applies to the arguments of themerge function

left,right

Since they are arrays:

lefts, rights

DRY

In thesort function, this expression is repeated a few times:

len(lst)

You could set that to a variable:

number = len(lst)

The code would be a little simpler and perhaps a little more efficient.

Simpler

For this line:

if len(left) > 0:

there is no need for the comparison. This is simpler:

if len(left):

There is no need for thisfor loop:

for i in l_rest:    out.append(i)

You could simply use theextend list method:

out.extend(l_rest)

The same is true for this loop:

for i in right:

Or, as seen in the previous answer,+ can also be used.

Documentation

ThePEP 8 style guide recommendsadding docstrings for functions. The docsrting should summarizewhat the function does, and it should describe the input types andreturn type. It should mention that thesort function is recursive.

answeredMar 12 at 18:42
toolic's user avatar
\$\endgroup\$
-2
\$\begingroup\$

Starting a wiki with the suggested edits in the comments so far.

def merge(left,right):    out = []    i = left[0]    while i is not None:        if right and i < right[0]:            out.append(i)            left.remove(i)        else:            out.append(right[0])            right.remove(right[0])         if len(left) > 0:             i = left[0]         else:             i = None    return out + left + rightdef sort(lst):    if len(lst) == 1:        return lst    left = sort(lst[:len(lst)//2])    right = sort(lst[len(lst)//2:])    return merge(left,right)
community wiki

\$\endgroup\$
1
  • \$\begingroup\$Thanks for posting this code. It's a good idea to summarise which changes you made, and why - a self-answer ought to review the code, just like any other answer.\$\endgroup\$CommentedMar 13 at 10:53

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.