I have three list, I want to convert into a specific dict
A = ["a", "b"]
B = ["10", "20"]
C = ["key1", "key2"]
I want a dict like that
"key1": {
"name": "a",
"age": 10
},
"key2": {
"name": "b",
"age": 20
}
I try different way by different step, but I don't get this dict
for key in A:
dict_A["name"].append(key)
Using a dictionary comprehension:
res = {key: {'name': name, 'age': age} for key, name, age in zip(C, A, B)}
This gives:
{'key1': {'age': '10', 'name': 'a'}, 'key2': {'age': '20', 'name': 'b'}}
zip allows you to aggregate elements from each iterable by index.
If you don't want to use zip then you can use enumerate as given below:
print ({v:{"name": A[k],"age": B[k]} for k, v in enumerate(C)})
In[1]: {c: {'name': a, 'age': b} for a, b, c in zip(A, B, C)}
Out[1]: {'key1': {'name': 'a', 'age': '10'}, 'key2': {'name': 'b', 'age': '20'}}
How about
for a,b,c in zip(A, B, C):
your_dict[c] = {"name" : a, "age": b}
Related
data = [
{
'name': 'Jack',
'points': 10
},
{
'name': 'John',
'points': 12
},
{
'name': 'Jack',
'points': 15
},
{
'name': 'Harry',
'points': 11
}
]
Output:
Jack: 25 points ,
John: 12 points ,
Harry: 11 points
Is there anyway to achieve this without using for loop ?
I can achieve this by storing key value pair or name and points and adding the points if already exists in the dictionary. But is there any alternative way to achieve this ?
You can use groupby from itertools:
from itertools import groupby
key = lambda d: d['name']
result = {n: sum(v['points'] for v in vs) for n, vs in groupby(sorted(data, key=key), key)}
Result:
{'Harry': 11, 'Jack': 25, 'John': 12}
I have a list of dictionaries, each containing two identical keys with possibly different values:
list_of_dicts = [
{'a': '1', 'b': '1'},
{'a': '4', 'b': '4'},
{'a': '1', 'b': '1'},
{'a': '3', 'b': '0'},
{'a': '1', 'b': '2'},
{'a': '4', 'b': '99'}
]
I want to rearrange this structure so that the values of one of the keys is a key, and the value is a dictionary of the other values (more keys will be added to these dictionaries later).
I also want to retain the different values for those keys (without duplicates). So the result should look like:
{'1': {'b': {'1', '2'}}, '4': {'b': {'4', '99'}}, '3': {'b': {'0'}}}
The purpose of this is to
remove duplicate values of 'a'
be able to call a dict based on the keys 1,4,3 in this example
retain the information held in the other key-value
This is the code I wrote to do this:
newdict = \
{d['a']: { #for each unique a value, build a dict with key b containing a set of all b values
'b':{d['b']} | {another_d['b'] for another_d in list_of_dicts if another_d['a'] == d['a']}
} \
for d in list_of_dicts}
but I'm wondering if there's a more idiomatic or cleaner way to write this? I tried using d.get() but I don't think it can be used.
Try:
list_of_dicts = [
{"a": "1", "b": "1"},
{"a": "4", "b": "4"},
{"a": "1", "b": "1"},
{"a": "3", "b": "0"},
{"a": "1", "b": "2"},
{"a": "4", "b": "99"},
]
out = {}
for d in list_of_dicts:
for k in d.keys() ^ "a":
out.setdefault(d["a"], {}).setdefault(k, set()).add(d[k])
print(out)
Prints:
{'1': {'b': {'1', '2'}}, '4': {'b': {'99', '4'}}, '3': {'b': {'0'}}}
This is my example :
dictlist = [{'Name': 'James', 'city': 'paris','type': 'A' },
{'Name': 'James','city': 'Porto','type': 'B'},
{'Name': 'Christian','city': 'LA','type': 'A'}]
I want to filter specific keys and values.
For example:
desiredKey = [Name,type]
desiredoutput = [{'Name': 'Lara', 'type': 'A' },
{'Name': 'James', 'type': 'B'},
{'Name': 'Christian','type': 'A'}]
I tried this, but it doesn't work
keys = dictlist[0].keys()
output= [d for d in dictlist if d.keys in desiredKey]
You can try something like this:
In [1]: dictlist = [{'Name': 'James', 'city': 'paris','type': 'A' },
...: {'Name': 'James','city': 'Porto','type': 'B'},
...: {'Name': 'Christian','city': 'LA','type': 'A'}]
In [2]: keys = ["Name","type"]
In [3]: res = []
In [5]: for dict1 in dictlist:
...: result = dict((k, dict1[k]) for k in keys if k in dict1)
...: res.append(result)
...:
In [6]: res
Out[6]:
[{'Name': 'James', 'type': 'A'},
{'Name': 'James', 'type': 'B'},
{'Name': 'Christian', 'type': 'A'}]
It's a bit more complicated than this answer but you can also use zip and itemgetter.
In [43]: list_of_dicts = [
...: {"a":1, "b":1, "c":1, "d":1},
...: {"a":2, "b":2, "c":2, "d":2},
...: {"a":3, "b":3, "c":3, "d":3},
...: {"a":4, "b":4, "c":4, "d":4}
...: ]
In [44]: allowed_keys = ("a", "c")
In [45]: filter_func = itemgetter(*allowed_keys)
In [46]: list_of_filtered_dicts = [
...: dict(zip(allowed_keys, filter_func(d)))
...: for d in list_of_dicts
...: ]
In [47]: list_of_filtered_dicts
Out[47]: [{'a': 1, 'c': 1}, {'a': 2, 'c': 2}, {'a': 3, 'c': 3}, {'a': 4, 'c': 4}]
This is an extension of this question. And this seems to show an example of appending to an array, not adding another value to a sub-dict.
dict_1 = {a: {price: 4000}, b: {price: 14000} }
dict_2 = {a: {discount: 0100}, b: {discount: 0400} }
dict_3 = {a: {amount: 41}, b: {amount: 522} }
I would like to merge them to be:
merged_dict: { a: {
price: 4000,
discount: 0100,
amount: 41
},
b: {
price: 14000,
discount: 0400,
amount: 522
}
}
How to achieve that? And how would that be if there was en even longer list of dictionaries to merge? The dictionaries will always have the same keys (a, b).
I tried doing the same as in the first hyperlink but the .items() seem to make it unscalable.
You can generalize this kind of merge by placing your dictionaries in a list and creating the merged dictionary in a comprehension:
dict_1 = {"a": {"price": 4000}, "b": {"price": 14000} }
dict_2 = {"a": {"discount": 100}, "b": {"discount": 400} }
dict_3 = {"a": {"amount": 41}, "b": {"amount": 522} }
dicts = [dict_1, dict_2, dict_3]
merged = { k:dict(kv for d in dicts for kv in d[k].items()) for k in dicts[0] }
print(merged)
{'a': {'price': 4000, 'discount': 100, 'amount': 41},
'b': {'price': 14000, 'discount': 400, 'amount': 522}}
I have a list of python dicts like this:
[{
'id': 1,
'name': 'name1'
}, {
'id': 2,
'name': 'name2'
}, {
'id': 3,
'name': 'name1'
}]
What I want to do is to create a new list of dictionaries, containing only the ones that have the key 'name' duplicated, and group them.
[{
'id1': 1,
'id2': 3,
'name': 'name1'
}]
The first list is an SQL query output and I need to delete the rows that have the key 'name' duplicated, keeping only one.
You can use itertools.groupby:
import itertools
d = [{'id': 1, 'name': 'name1'}, {'id': 2, 'name': 'name2'}, {'id': 3, 'name': 'name1'}]
new_data = [[a, list(b)] for a, b in itertools.groupby(sorted(d, key=lambda x:x['name']), key=lambda x:x['name'])]
final_dicts = [{'name':a, **{f'id{i}':a['id'] for i, a in enumerate(b, 1)}} for a, b in new_data if len(b) > 1]
Output:
[{'name': 'name1', 'id1': 1, 'id2': 3}]
I suggest you the following solution, quite easy to read and understand:
from collections import defaultdict
ds = [{'id': 1, 'name': 'name1'},
{'id': 2, 'name': 'name2'},
{'id': 3, 'name': 'name1'}]
newd = defaultdict(list)
for d in ds:
newd[d['name']].append(d['id'])
# Here newd is {'name1': [1, 3], 'name2': [2]}
result = []
for k,v in newd.items():
if len(v) > 1:
d = {f'id{i}':i for i in v}
d['name'] = k
result.append(d)
print(result) # [{'id1': 1, 'id3': 3, 'name': 'name1'}]
You can use collections.Counter:
from collections import Counter
from operator import itemgetter
l = [{'id': 1, 'name': 'name1'}, {'id': 2, 'name': 'name2'}, {'id': 3, 'name': 'name1'}]
print([{'name': n, **{'id%d' % i: d['id'] for i, d in enumerate([d for d in l if d['name'] == n], 1)}} for n, c in Counter(map(itemgetter('name'), l)).items() if c > 1])
This outputs:
[{'name': 'name1', 'id1': 1, 'id2': 3}]