Is there a way to shorten this loop into one line? - python

anyway to make this one line, but without list comprehension?
for x in someDict["place"]: # make this
for thing in x: # and this one line?
print(x[thing]["this_des1"])
print(x[thing]["that_des2"])
someDict = {
"place": [ { 0 : { "this_des1": 'data1', "that_des2" : 'data2' } },
{ 1 : { "this_ces1": 'data3', "that_ces2" : 'data4' } } ] }

Since your dicts have different keys, and it seems like you're trying to print all of the bottom-level values, it'd be easier to use values() rather than hardcoding the keys.
>>> print('\n'.join(z for x in someDict["place"] for y in x.values() for z in y.values()))
data1
data2
data3
data4

Related

python replace json list values without knowing the keys

I have this code snippet:
data = {
"links": [
{"key_name_not_known": "replace_by_first_value_in_list"},
{"key_name_not_known": "replace_by_second_value_in_list"},
]
}
list = ["hello1", "hello2"]
Here I want to replace both values "hello" in data["links"] ["keys"]? without knowing the key value by the two values in the list, in the right order.
A goal output would be:
data = {
"links": [
{"key_name_not_known": "hello1"},
{"key_name_not_known": "hello2"},
]
}
How can I do that ?
for index, obj in enumerate(data['links']):
for key,val in obj.items():
if len(list) > index:
data['links'][index][key] = list[index]

Fastest way to get values from dictionary to another dictionary in python without using if?

I need to find a way to get values from one dictionary to another, bases on key name match without using two loops \ if statement.
Main goal is to make it run more efficiently since it's a part of a larger code and run on multiple threads.
If you can keep the dictionary structure it would help
The second dict is initialized with values 0 in advanced
dict_1 = {
"school": {
"main": ["first_key"]
},
"specific": {
"students": [
{
"name": "sam",
"age": 13
},
{
"name": "dan",
"age": 9
},
{
"name": "david",
"age": 20
},
{
"name": "mike",
"age": 5
}
],
"total_students": 4
}
}
dict_2 = {'sam': 0, 'mike': 0, 'david': 0, 'dan': 0, 'total_students': 0}
for i in dict_1["specific"]['students']:
for x in dict_2:
if x == i["name"]:
dict_2[x] = i["age"]
dict_2["total_students"] = dict_1["specific"]["total_students"]
print(dict_2)
Is there more elegant way of doing it?
You don't need two loops at all! You don't even need to initialize dict_2 in advance. Simply loop over dict_1["specific"]["students"] and assign the ages to dict_2 without an if.
for student in dict_1["specific"]["students"]:
student_name = student["name"]
student_age = student["age"]
dict_2[student_name] = student_age
You could also write this as a comprehension:
dict_2 = {student["name"]: student["age"] for student in dict_1["specific"]["students"]}
Both these give the following dict_2:
{'sam': 13, 'dan': 9, 'david': 20, 'mike': 5}
Then you can set dict_2["total_students"] like you already do, but outside any loops.
dict_2["total_students"] = dict_1["specific"]["total_students"]
If you only want to assign ages for students already in dict_2, you need the if. However, you can still do this with a single loop instead of two. :
for student in dict_1["specific"]["students"]:
student_name = student["name"]
if student_name not in dict_2:
continue # skip the rest of this loop
student_age = student["age"]
dict_2[student_name] = student_age
Both these approaches use a single loop, so they're going to be faster than your two-loop approach.
for i in dict_1['specific']['students']:
dict_2[i['name']]=i['age']
dict_2['total_students']=dict_1['specific']['total_students']
Runs in O(N) time and O(N) space.
Yours currently runs in O(N^2) time and O(N) space

Merging 2 dictionaries in python

I have two dictionary:
a=
{
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
},
....
}
and
b=
{
"2001935072": {
"wtr": 816
},
....
}
i've tried to merge them with both a.update(b) and a={**a, **b} but both gives this output when i print(a):
{
"2001935072": {
"wtr": 816
},
....
}
which is basicly a=b, how to merge A and B so the output is
{
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
"wtr": 816
},
....
}
I would compute the union of the keys, then rebuild the dictionary merging the inner dictionaries together with an helper method (because dict merging is possible in 3.6+ inline but not before) (How to merge two dictionaries in a single expression?)
a={
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
}
}
b= {
"2001935072": {
"wtr": 816
},
}
def merge_two_dicts(x, y):
"""Given two dicts, merge them into a new dict as a shallow copy."""
z = x.copy()
z.update(y)
return z
result = {k:merge_two_dicts(a.get(k,{}),b.get(k,{})) for k in set(a)|set(b)}
print(result)
result:
{'2001935072': {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2, 'wtr': 816}}
notes:
a.get(k,{}) allows to get the value for k with a default of so merge still works, only retaining values from b dict.
merge_two_dicts is just an helper function. Not to be used with a and b dicts directly or it will give the wrong result, since last merged one "wins" and overwrites the other dict values
With Python 3.6+: you can do that without any helper function:
result = {k:{**a.get(k,{}),**b.get(k,{})} for k in set(a)|set(b)}
Try this:-
for i,j in a.items():
for x,y in b.items():
if i==x:
j.update(y)
print(a) #your updateed output
You can try list + dict comprehension to achieve your results:
>>> a = {"2001935072":{"WR":"48.9","nickname":"rogs30541","team":2}}
>>> b = {"2001935072":{"wtr":816}}
>>> l = dict([(k,a.get(k),b.get(k)) for k in set(list(a.keys()) + list(b.keys()))])
This will output:
>>> [('2001935072', {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2}, {'wtr': 816})]
Finally to achieve your desired output
>>> dict((k,{**va,**vb}) for k,va,vb in l)
>>> {'2001935072': {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2, 'wtr': 816}}

Remove duplicate of a dictionary from list

How can i remove duplicate of the key "name"
[
{
'items':[
{
'$oid':'5a192d0590866ecc5c1f1683'
}
],
'image':'image12',
'_id':{
'$oid':'5a106f7490866e25ddf70cef'
},
'name':'Amala',
'store':{
'$oid':'5a0a10ad90866e5abae59470'
}
},
{
'items':[
{
'$oid':'5a192d2890866ecc5c1f1684'
}
],
'image':'fourth shit',
'_id':{
'$oid':'5a106fa190866e25ddf70cf0'
},
'name':'Amala',
'store':{
'$oid':'5a0a10ad90866e5abae59470'
}
}
]
I want to marge together dictionary with the same key "name"
Here is what i have tried
b = []
for q in data:
if len(data) == 0:
b.append(q)
else:
for y in b:
if q['name'] != y['name']:
b.append(q)
but after trying this the b list doesn't return unique dictionary that i wanted
You loop through the assembled list and if you find a dict with a different name, you add the current dict. The logic should be different: only add it if you don't find one with the same name!
That being said, you should maintain a set of seen names. That will make the check more performant:
b, seen = [], set()
for q in data:
if q['name'] not in seen:
b.append(q)
seen.add(q['name'])

python nested dict in array group sum

I have this data structure in Python:
result = {
"data": [
{
"2015-08-27": {
"clicks": 10,
"views":20
}
},
{
"2015-08-28": {
"clicks": 6,
}
}
]
}
How can I add the elements of each dictionary? The output should be :
{
"clicks":16, # 10 + 6
"views":20
}
I am looking for a Pythonic solution for this. Any solutions using Counter are welcome but I am not able to implement it.
I have tried this but I get an error:
counters = []
for i in result:
for k,v in i.items():
counters.append(Counter(v))
sum(counters)
Your code was quite close to a workable solution, and we can make it work with a few important changes. The most important change is that we need to iterate over the "data" item in result.
from collections import Counter
result = {
"data": [
{
"2015-08-27": {
"clicks": 10,
"views":20
}
},
{
"2015-08-28": {
"clicks": 6,
}
}
]
}
counts = Counter()
for d in result['data']:
for k, v in d.items():
counts.update(v)
print(counts)
output
Counter({'views': 20, 'clicks': 16})
We can simplify that a little because we don't need the keys.
counts = Counter()
for d in result['data']:
for v in d.values():
counts.update(v)
The code you posted makes a list of Counters and then tries to sum them. I guess that's also a valid strategy, but unfortunately the sum built-in doesn't know how to add Counters together. But we can do it using functools.reduce.
from functools import reduce
counters = []
for d in result['data']:
for v in d.values():
counters.append(Counter(v))
print(reduce(Counter.__add__, counters))
However, I suspect that the first version will be faster, especially if there are lots of dicts to add together. Also, this version consumes more RAM, since it keeps a list of all the Counters.
Actually we can use sum to add the Counters together, we just have to give it an empty Counter as the start value.
print(sum(counters, Counter()))
We can combine this into a one-liner, eliminating the list by using a generator expression instead:
from collections import Counter
result = {
"data": [
{
"2015-08-27": {
"clicks": 10,
"views":20
}
},
{
"2015-08-28": {
"clicks": 6,
}
}
]
}
totals = sum((Counter(v) for i in result['data'] for v in i.values()), Counter())
print(totals)
output
Counter({'views': 20, 'clicks': 16})
This is not the best solution as I am sure that there are libraries that can get you there in a less verbose way but it is one you can easily read.
res = {}
for x in my_dict['data']:
for y in x:
for t in x[y]:
res.setdefault(t, 0)
res[t] += x[y][t]
print(res) # {'views': 20, 'clicks': 16}

Categories

Resources