Filter all dicts in a list to be with specific keys and ignore others? - python-3.x

I have the following list of dicts:
lst = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'd':3}, {'a':1, 'c':2, 'k':3}, {'d':1, 'k':2, 'l':3}]
I want to filter the list of dicts (in my case it's a list of thousands or even more dicts, with different keys with some overlap) to be a list containing all the dicts that have keys: ["a", "b"]. I want to filter each dict only to these a and b keys, and if they don't exist, don't include the dictionary in the final list. I am using:
[{"a": d.get("a"), "b": d.get("b")} for d in lst]
Please advise for an elegant way to solve it.

The dictionary keys-view is set-like, so it supports subset comparisons by using <= operator:
>>> keys = set("ab")
>>> [{k: d[k] for k in keys} for d in lst if keys <= d.keys()]
[{'a': 1, 'b': 2}, {'a': 1, 'b': 2}]

I have figured it out and here is my alternative:
lst = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'd':3}, {'a':1, 'c':2, 'k':3}, {'d':1, 'k':2, 'l':3}]
keys = set("ab")
[i for i in [{k: d.get(k) for k in keys if k in d} for d in lst] if i]
Gives the desired answer:
[{'b': 2, 'a': 1}, {'b': 2, 'a': 1}, {'a': 1}]

Related

Merge two dictionaries that have dictionaries as key values

Merge two dictionaries of dictionaries
My question is similar to this one, but the answers don't produce the right result (for me?).
Take these dictionaries:
a = {'a': {'a': 1}}
b = {'a': {'b': 2}}
I want to produce:
c = {'a': {'a': 1, 'b': 2}}
Using the answers from the quoted question, these all produce:
c = a.copy()
c.update(b)
>>
c == {'a': {'b': 2}
Consider that a and b might be more complex than this, for example:
a = {'a': {'aa': {'aaa': 1}, 'bb': {'bbb': 2}}}
b = {'a': {'bb': {'aaa': 1}, 'bb': {'bbb': 2}}}
In this case you can use
>>> a['a'].update(b['a'])
>>> a
{'a': {'a': 1, 'b': 2}}
Element in dictionary is also dictionary, so you can treat that element as dictionary.
As for more complex example I don't know what result should be. But in general, you can access elements in element as dictionary in nested for loops.

I have a list of dictionaries, that have same keys and some have different values for those keys

mylist = [{'a': 'banana'}, {'a': 'orange'}, {'b': 'apple'}, {'c': 'grapes'}, {'b': 'banana'}, {'c': 'apple'}]
I want to change this into a dictionary with same keys to have list of value like so:
mylist = [{'a': 'banana', 'orange'}, {'b': 'apple', 'banana'}, {'c': 'grape' 'apple'}]
My code:-
mydict_ = defaultdict(list)
for x in mylist:
for k, v in x.items():
mydict_[k].append(v)
mydict = dict(mydict_)
print(mydict)
I am getting:-
mylist = [{'a': 'banana', 'banana'}, {'b': 'apple', 'apple'}, {'c': 'grapes', 'grapes'}]
Do this in your loop:
for x in mylist:
for k,v in x.items():
if(k in mydict):
mydict[k].append(v)
else:
mydict[k]=[v]
from collections import defaultdict
new_dict = defaultdict(list)
for key_value_pair in mylist:
key, value = list(key_value_pair.items())[0]
new_dict[key].append(value)
ans_dict = dict(new_dict)

Python Groupby keys list of dictionaries

I have the following for instance:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
and I would like to get a dictionary like this:
x = [{'A': [1,2], 'B': [1,2,3], 'C':[1], 'D': [1]}]
Do you have any idea how I could get this please?
You could use a collections.defaultdict of sets to collect unique values, then convert the final result to a dictionary with values as lists using a dict comprehension:
from collections import defaultdict
lst = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
result = defaultdict(set)
for dic in lst:
for key, value in dic.items():
result[key].add(value)
print({key: list(value) for key, value in result.items()})
Output:
{'A': [1, 2], 'B': [1, 2, 3], 'C': [1], 'D': [1]}
Although its probably better to add your data directly to the defaultdict to begin with, instead of creating a list of singleton dictionaries(don't recommend this data structure) then converting the result.
Using dict.setdefault
Ex:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
res = {}
for i in x:
for k, v in i.items():
res.setdefault(k, set()).add(v)
#or res = [{k: list(v) for k, v in res.items()}]
print(res)
Output:
{'A': {1, 2}, 'B': {1, 2, 3}, 'C': {1}, 'D': {1}}

How to get list of indexes for unique values?

Having a list like this
lst = ['a','b','a','c','a','b','b']
I'd like to get lists of indexes for each unique element to get this:
indexes = {
'a': [0,2,4],
'b': [1,5,6],
'c': [3]
}
This is my current code, but I'm only getting the first index of each element.
indexes= dict()
for el in lst:
indexes[el] = [lst.index(el)]
>>> indexes
{'a': [0], 'b': [1], 'c': [3]}
Thanks for any help.
The problem with you code is you're overriding the same key again and again but with a different list, so your final dictionary contains only a single list.
you can avoid this behavior by using defaultdict.
from collections import defaultdict
lst = ["a", "b", "a", "c", "a", "b", "b"]
lst = [c for c in lst if c.strip()] # this will remove empty strings
indexes = defaultdict(list)
for index, char in enumerate(lst):
indexes[char].append(index)
indexes = dict(indexes)
print(indexes)
Output:
{'a': [0, 2, 4], 'b': [1, 5, 6], 'c': [3]}

generate items from dictionary

I'm using python 3.3
I have a dictionary
dict = {'a': (3,1), 'b': (1,2), 'c': (1,1)}
i'm trying to generate one item at a time
when I write item I mean
item1 = 'a': (3,1)
item2 = 'b': (1,2)
etc'
i have tried:
for key, value in dict.items():
temp = [key, value]
yield temp
or
for item in dict:
yield dict[item],item
but both don't generate what I want.
any help will be greatly appreciated
Thanks!
def my_generator(d):
for key, value in d.items():
yield {key: value}
d = {'a': (3,1), 'b': (1,2), 'c': (1,1)}
for subdict in my_generator(d):
print subdict
This would yield:
{'a': (3,1)}
{'b': (1,2)}
{'c': (1,1)}

Resources