简体   繁体   中英

Merge sorted arrays into single sorted array: Python

I want to sort two already sorted arrays into one. I am using merge sort for this purpose.

Error:: IndexError: list index out of range

I have tried checking out this manually and I couldnt find out of range arrays. Please correct me if I am wrong

def merging(list1, list2):
    m = len(list1)
    n = len(list2)
    val = m+n
    j, k =  0, 0
    new =[]
    for i in range(val):
        if j<m and k<n:
           if list1[j] < list2[k]:
              new.append(list1[j])
              j += 1
           else:
              new.append(list2[k])     
              k += 1

       elif j==m:
          while i<m+n:
            new.append(list2[k])
            k += 1
            i += 1
       else:
        while i<m+n:
            new.append(list1[j])
            j += 1
            i += 1

print 'sorted array is:', new

if __name__ == '__main__':
    print 'Enter list 1'
    l1 = raw_input()
    list1 = map(int, l1.split())
    print 'Enter list 2'
    l2 = raw_input()
    list2 = map(int, l2.split())
    merging(list1,list2)

EDIT:: I do not want to use any built in functions like sort()

You have two problems:

  1. You don't break when you reach the elif or else cases, so the outer loop continues (and the for loop ignores the changes to i made inside the loop); and
  2. You never return new .

The minimal fix is:

def merging(list1, list2):
    m = len(list1)
    n = len(list2)
    val = m+n
    j, k =  0, 0
    new =[]
    for i in range(val):
        if j<m and k<n:
             if list1[j] < list2[k]:
                new.append(list1[j])
                j += 1
             else:
                new.append(list2[k])     
                k += 1

        elif j==m:
            while i<m+n:
                new.append(list2[k])
                k += 1
                i += 1
            break # stop for loop here
        else:
            while i<m+n:
                new.append(list1[j])
                j += 1
                i += 1
            break # or here
    return new # and return the output

But you could apply the same logic more neatly:

def merge(l1, l2):
    """Merge the sorted lists into a new, single list."""
    i = j = 0
    out = []
    while True:
        if i == len(l1):
            out.extend(l2[j:])
            break
        elif j == len(l2):
            out.extend(l1[i:])
            break
        elif l1[i] <= l2[j]:
            out.append(l1[i])
            i += 1
        else:
            out.append(l2[j])
            j += 1
    return out

Sorry for confuse.

The problem is that you can't change the value of i, for i is in range(val).

def merging(list1, list2):
    m = len(list1)
    n = len(list2)
    val = m+n
    j, k =  0, 0
    new =[]
    for i in range(val):
        if j<m and k<n:
           if list1[j] < list2[k]:
              new.append(list1[j])
              j += 1
           else:
              new.append(list2[k])     
              k += 1

        elif j==m:
          if k<n:
              new.append(list2[k])
              k += 1
        else:
          if j<m:
                new.append(list1[j])
                j += 1

    print "sorted array is:"
    print new

if __name__ == '__main__':
    print 'Enter list 1'
    l1 = raw_input()
    list1 = map(int, l1.split())
    print 'Enter list 2'
    l2 = raw_input()
    list2 = map(int, l2.split())
    merging(list1,list2)
def merging(list1, list2):
    m = len(list1)
    n = len(list2)
    res = []
    a, b = 0, 0
    while a < m and b < n:
        if list1[a] < list2[b]:
            res.append(list1[a])
            a += 1
        else:
            res.append(list2[b])
            b += 1
    if a == m:
        for i in list2[b:]:
            res.append(i)
    else:
         for i in list1[a:]:
             res.append(i)
    return res

if __name__ == '__main__':
    print 'Enter list 1'
    l1 = raw_input()
    list1 = map(int, l1.split())
    print 'Enter list 2'
    l2 = raw_input()
    list2 = map(int, l2.split())
    print merging(list1,list2)

Here's a version that returns a generator and works with all iterables:

def merge(g1, g2):
    i1, i2 = iter(g1), iter(g2)
    e1, e2 = None, None
    try:
        e1 = next(i1)
        e2 = next(i2)
        while True:
            if e1 < e2:
                yield e1
                e1 = None
                e1 = next(i1)
            elif e2 < e1:
                yield e2
                e2 = None
                e2 = next(i2)
            else:
                yield e1
                yield e2
                e1, e2 = None, None
                e1 = next(i1)
                e2 = next(i2)
    except(StopIteration):
        for ix, ex in ((i1, e1), (i2, e2)):
            if ex != None:
                yield ex
                for e in ix:
                    yield e

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM