Rowan Clarke
Rowan Clarke

Reputation: 13

Searching for something thats not in a list

Basically I'm trying to search a list from a list (not sure if they are actually lists or dictionary, but I've included the exact input) and if item from list 1 is not in list 2 I want to remove it from list 1, what ever I do all I get is what's in the list and not what's not in the list.

import datetime

listone = {}
listtwo = []
listone["https://www.somesite.com.au/1"]= datetime.datetime.now()
listone["https://www.somesite.com.au/2"]= datetime.datetime.now()
listone["https://www.somesite.com.au/3"]= datetime.datetime.now()

listtwo.append(["http://www.not.com/not1","test 1"])
listtwo.append(["http://www.not.com/not2","test 6"])
listtwo.append(["http://www.not.com/not3","test 5"])
listtwo.append(["http://www.not.com/not4","test 4"])
listtwo.append(["http://www.not.com/not5","test 3"])
listtwo.append(["http://www.not.com/not6","test 2"])
listtwo.append(["https://www.somesite.com.au/2", "test 1"])

temp = listone.copy()
for key, value in temp.items():
    for item in listtwo:
        if item[0] != key:
            listone.pop(item[0], None)
print(listone)

Now I'm only getting back somesite 1 and 3 in listone after the code has ran, which it should be somesite 2 in listone and 1 and 3 should be removed. Can someone point out where I'm going wrong please?

Upvotes: 1

Views: 105

Answers (2)

Óscar López
Óscar López

Reputation: 236014

You need to test if an element is not in the whole list of filtered elements before deciding to remove it. There's a simpler solution: first, extract the items that you want to use for filtering. I'll use a set for efficiency and a generator expression for extracting the URLs:

urls = set(url for url, text in listtwo)

Then, create a new dictionary without the elements that you want to filter; here I'm using a dictionary comprehension:

listone = {k: v for k, v in listone.items() if k in urls}

The result will be as expected:

listone
=> {'https://www.somesite.com.au/2': datetime.datetime(2021, 4, 15, 13, 38, 20, 388197)}

By the way, listone is actually a dictionary, not a list.

Upvotes: 1

gold_cy
gold_cy

Reputation: 14226

It sounds like you don't quite understand the logic you wrote. In your first iteration of the loop, key is equal to https://www.somesite.com.au/1. The nested loop, for item in listtwo will then have item[0] try to pop a value from temp if it does not match https://www.somesite.com.au/1. In that first iteration none of the values of item[0] will match so your if statement is met for every iteration of the loop. None of the values of item[0] are in temp besides the last one, "https://www.somesite.com.au/2". Therefore, when you reach the final iteration of the loop it will remove that value from temp.

If we modify the code to print what it plans to pop and what it actually removes you can see what I describe happen.

Going to try to pop -> http://www.not.com/not1
Actually popped -> None
Going to try to pop -> http://www.not.com/not2
Actually popped -> None
Going to try to pop -> http://www.not.com/not3
Actually popped -> None
Going to try to pop -> http://www.not.com/not4
Actually popped -> None
Going to try to pop -> http://www.not.com/not5
Actually popped -> None
Going to try to pop -> http://www.not.com/not6
Actually popped -> None
Going to try to pop -> https://www.somesite.com.au/2
Actually popped -> 2021-04-15 07:50:10.448479
....

That is the reason your code is not working as expected.

Upvotes: 0

Related Questions