21

I have a dictionary dict2 which I want to iter through and remove all entries that contain certain ID numbers in idlist. dict2[x] is a list of lists (see example dict2 below). This is the code I have written so far, however it does not remove all instances of the IDs (entry[1]) that are in the idlist. Any help?

dict2 = {G1:[[A, '123456', C, D], [A, '654321', C, D], [A, '456123', C, D], [A, '321654', C, D]]}

idlist = ['123456','456123','321654']
for x in dict2.keys():
    for entry in dict2[x]:
        if entry[1] in idlist:
            dict2[x].remove(entry)
        if dict2[x] == []:
            del dict2[x]

dict2 should end up looking like this :

dict2 = {G1:[[A, '654321', C, D]]}
marsx
  • 715
  • 4
  • 10
  • 15

2 Answers2

34

Try a cleaner version perhaps?

for k in dict2.keys():
    dict2[k] = [x for x in dict2[k] if x[1] not in idlist]
    if not dict2[k]:
        del dict2[k]
Amber
  • 507,862
  • 82
  • 626
  • 550
  • Note that you [can't modify a dict while iterating over it](http://stackoverflow.com/questions/5384914/deleting-items-from-a-dictionary-while-iterating-over-it/5385075#5385075), so @marsx was right to iterate over `dict2.keys()` instead. – Ben Hoyt Jun 13 '11 at 15:47
  • @benhoyt - you're right; I initially took it out because I forgot about the `del`, but then put the `del` in and didn't swap it back. :) – Amber Jun 13 '11 at 15:48
  • @Amber I didnt type it right but the ID numbers are all strings. I tried your code and I got this error `dict2[x] = [x for x in dict2[k] if x[1] not in idlist] TypeError: list objects are unhashable`. I dont know if this makes a difference but the real dict2 contains datetime objects and other lists aswell. – marsx Jun 13 '11 at 15:52
  • If you're getting that error, your `dict2` has an additional layer of nesting beyond what you wrote here, or the wrong index in the list is being used. – Amber Jun 13 '11 at 15:56
  • @Amber should it be `dict2[k] = [x for x in dict2[k] if x[1] not in idlist]` ? `dict2[x]` doesnt make sense if you're calling the lists `x` – marsx Jun 13 '11 at 16:00
15

An approach using sets (Note that I needed to change your variables A, B, C, etc. to strings and the numbers in your idlist to actual integers; also this only works, if your IDs are unique and don't occur in other 'fields'):

#!/usr/bin/env python
# 2.6 <= python version < 3

original = {
    'G1' : [
        ['A', 123456, 'C', 'D'], 
        ['A', 654321, 'C', 'D'], 
        ['A', 456123, 'C', 'D'], 
        ['A', 321654, 'C', 'D'],
    ]
}

idlist = [123456, 456123, 321654]
idset = set(idlist)

filtered = dict()

for key, value in original.items():
    for quad in value:
        # decide membership on whether intersection is empty or not
        if not set(quad) & idset:
            try:
                filtered[key].append(quad)
            except KeyError:
                filtered[key] = quad

print filtered
# would print:
# {'G1': ['A', 654321, 'C', 'D']}
miku
  • 181,842
  • 47
  • 306
  • 310