user2592166
user2592166

Reputation: 11

List accessing in Python

I have a two list like this

Nodelist1=[[['B', 10], ['IN', 1000]], [['C', 15], ['OUT', 1001]], [['F', 30], ['IN', 1100]]]
Nodelist2= [[['G', 20], ['IN', 1000, 'OUT', 1111]], [['D', 25], ['INWARD', 1]]]

What I am trying to do is I am comparing these two lists like this

if len(Nodelist1[i][1])==len(Nodelist2[j][1]) 

If condition is true then I want to remove Nodelist1[i][0] which is ['B', 10] and from Nodelist1 and Nodelist2[j][1] which is ['D', 25] from Nodelist2.

Then I should have

Nodelist1 as [[['C', 15], ['OUT', 1001]], [['F', 30], ['IN', 1100]]]
Nodelist2 as [[['G', 20], ['IN', 1000, 'OUT', 1111]]]

My code is like this:

   if len(Nodelist1)>len(Nodelist2):
      for i in range(len(Nodelist1)):
         for j in range(len(Nodelist2)):
            if len(Nodelist1[i][1])==len(Nodelist2[j][1]):
                if Nodelist1[i][1]==Nodelist2[j][1]:
                    Nodelist1.remove(Nodelist1[i])
                    Nodelist2.remove(Nodelist2[j])  
                else:
                    Nodelist1.remove(Nodelist1[i])
                    Nodelist2.remove(Nodelist2[j])  

It gives me an error:

if len(Nodelist1[i][1])==len(Nodelist2[j][1]):
    IndexError: list index out of range

Upvotes: 1

Views: 169

Answers (3)

twil
twil

Reputation: 6162

It is rather bad idea to remove items from list iterating the way you do, e.g.

for i in range(len(Nodelist1)):
    pass

You could do something like this:

if len(Nodelist1)>len(Nodelist2):
    # store indexes of items to remove
    list1_to_del = []
    list2_to_del = []
    for i, item1 in enumerate(Nodelist1):
        for j, item2 in enumerate(Nodelist2):
            if len(item1) == len(item2):
                list1_to_del.append(i)
                list2_to_del.append(j)
             else:
                pass # not sure of your intensions and indentation

    # filter lists
    if list1_to_del:
        Nodelist1 = [item for i, item in enumerate(Nodelist1) if i not in set(list1_to_del)]
    if list2_to_del:
        Nodelist2 = [item for i, item in enumerate(Nodelist12) if i not in set(list2_to_del)]

But solution is somewhat clumsy:/

Upvotes: 1

Maxime Chéramy
Maxime Chéramy

Reputation: 18841

You should probably not use for i in range(len(your_list)) while you could simply do for val in your_list (or enumerate). But that is not the problem.

The problem is that you are removing elements in the list while iterating over it. The indexes are shifted. For example, if you are removing the element at index i, the next element has index i now. However you do i+=1 in your loop.

A solution would be to keep a list of elements to remove and remove them at the end, after your loop.

Also:

            if Nodelist1[i][1]==Nodelist2[j][1]:
                Nodelist1.remove(Nodelist1[i])
                Nodelist2.remove(Nodelist2[j])  
            else:
                Nodelist1.remove(Nodelist1[i])
                Nodelist2.remove(Nodelist2[j])

Both then and else cases are doing the same thing... It makes no sense.

Upvotes: 0

zhangyangyu
zhangyangyu

Reputation: 8610

You are removing elements from a list while looping through it. So when you are moving to the end of the list, there are not enough elements. And the index accessing will raise an IndexError.

Upvotes: 5

Related Questions