1

I try to remove all characters in the database that are smaller than a chosen character i. The database is a list of lists of characters.

def project(database, i):
    test = database.copy()
    for idx,lists in enumerate(database.copy()):
        for char in lists:
            print(char)
            if char <= i:
                test[idx].remove(char)
     return test

a = [['A','B','D'],['A','B','C','D']]
print(project(a, 'C'))


Output:
A D A C
[['B', 'D'], ['B', 'D']]

Somehow the code never checks for 'B' although it is in the list. The same code without the if condition + remove line (line 5-6) does the following:

Output:
A B D A B C D
['A', 'B', 'D'], ['A', 'B', 'C', 'D']]

Why does the printed character change although I do not change the iterated list?

5
  • test is not a copy of the database. Well, it is - but it is a shallow copy. It contains references to the original inner lists. You need a deep copy. Commented Aug 29, 2017 at 0:09
  • I was afraid that changing the matrix that I am iterating through maybe explains the weird behaviour. I just checked the code without all copies, it does the same. Commented Aug 29, 2017 at 0:13
  • Please read the answers, at least one of them explains how to make a deep copy. Commented Aug 29, 2017 at 0:16
  • Deep copy fixed this how? Commented Aug 29, 2017 at 0:25
  • Possible duplicate of Why is my for loop skipping an element in my list? Commented Aug 29, 2017 at 0:41

3 Answers 3

1

After debugging:

The issue is not because of your if statement, It is because remove change the index.

Let mt demonstrate that:

  • after first iterate with removing A the list will be:

    ["B", "D"]
    

And your index will be 1, because of that "B" will be ignored.

Sign up to request clarification or add additional context in comments.

Comments

0

Your issue has to do with your copying of the list database.

Per the python.org docs:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

If you deep copy copy.deepcopy(x) your list, then you will get a separate object that is not a reference of the other, but rather, a full copy.

1 Comment

Also see This question
0

As it has been already mentioned in the other answers, your code has two issues: one with shallow copying and the other with modifying the list that is being iterated. However, you do not even need all this complexity. In your case, it is cheaper to retain the "good" items than to remove the "bad" items:

def project(database, i):
    return [[item for item in lst if item >= i] for lst in database]

print(project(a, 'C'))
# [['D'], ['C', 'D']]

By the way, the condition char <= i removes the items that are smaller than or equal to i, not just smaller than i.

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.