0

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()

7
  • Can you give the lists for which it doesn't work. There are some cases where this works. Commented Aug 7, 2014 at 9:29
  • Anyway, you do realize that the simplest Commented Aug 7, 2014 at 9:30
  • It works fine when size of list1 is bigger than list2 Commented Aug 7, 2014 at 9:32
  • 1
    Anyway, yo do realize that the simplest way is: l_new = list1 + list2; l_new.sort() Commented Aug 7, 2014 at 9:32
  • I have told that i do not want to use predefined functions! Commented Aug 7, 2014 at 9:36

4 Answers 4

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

0
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)

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.