I have the following list of dicts as follows:
l1=[{"key1":"a1","key2":"a2"}, {"key1":"b1","key2":"b2"},
{"key1":"c1","key2":"c2"}, {"key1":"a2","key2":"a1"},
{"key1":"c2","key2":"c1"}, ....]
I want to remove the repeated elements in the dict.For example,if I have a1 and a2, once in the list of dicts,I don't want them again.So,in the above example,I don't want the dicts
{"key1":"a2","key2":"a1"},{"key1":"c2","key2":"c1"}
How do I delete them? Basically I want to remove the dicts having same values irrespective of their order. I have tried the following code:
for i in range(0,len(l1)):
for key,val in l1[i].items():
if l[i][key]==l[i+1][key]
del l[i+1][key]
This doesn't work
Use a defaultdict(list)
to collect under keys of frozenset
of the values of your source list inner dict's and collect the actual dicts as values.
Iterate the defaultdict(list)
and keep f.e. the 1st entry of each of its value lists:
l1=[{"key1":"a1","key2":"a2"},{"key1":"b1","key2":"b2"},
{"key1":"c1","key2":"c2"},{"key1":"a2","key2":"a1"},
{"key1":"c2","key2":"c1"}]
from collections import defaultdict
d = defaultdict(list)
# store dicts under the values of itself - use frozendict for key to
# ignore order of values
for inner in l1:
d[frozenset(inner.values())].append(inner)
# construct new dict by f.e. keeping the first dict out of each list
l2 = [v[0] for _,v in d.items()]
# pretty print them
from pprint import pprint
pprint(d)
pprint(l2)
Output:
# intermediate dict
defaultdict(<class 'list'>,
{frozenset({'a1', 'a2'}): [{'key1': 'a1', 'key2': 'a2'},
{'key1': 'a2', 'key2': 'a1'}],
frozenset({'b2', 'b1'}): [{'key1': 'b1', 'key2': 'b2'}],
frozenset({'c1', 'c2'}): [{'key1': 'c1', 'key2': 'c2'},
{'key1': 'c2', 'key2': 'c1'}]})
# resulting dict
[{'key1': 'a1', 'key2': 'a2'},
{'key1': 'b1', 'key2': 'b2'},
{'key1': 'c1', 'key2': 'c2'}]
See defaultdict abd pretty printer
In case you can not use defaultdict, you can use a normal one as well - it is just not as performant:
d = {}
for inner in l1:
d.setdefault(frozenset(inner.values()),[]).append(inner)
When I use defaultdict,the code starting from that line doesn't work anymore.It is something wierd.Does it got something to do with version thing?
@sam version thing? What version do you use? You can use a normal dict as well if you do:
d = {}; for inner in l1: d.setdefault(frozenset(inner.values()),[]).append(inner)
- this is somewhat less performant thoughworks with dict