Creating a defining dictionary in python (glossary and input) - python

I already have all the code done, I am just needing help on how I can get all my words, I have previously done databases before with countries, currencies, and leaders of the world, ect... but now I need definitions, can someone point me in the right way?
CCCdatbase = [
{
"country": "Afghanistan",
"capital": "Kabul",
"currency": "Afghani",
"language": "Dari Persian; Pashto",
"leader": "Amrullah Saleh",
"k2": ""
},
]
#except like this:
dictionary = [
{
"word": 'dog',
"definition": "worse than cats"
}
]```

Why not
dictionary = [
{
'dog': 'worse than cats',
'cat': 'feline...'
}
]```

Related

Merge same dictionary value into one list

I am new in python and I am trying to list comprehsion my list dictionaries.
I have a serialized response in dictionaries inside list like :-
[
{
"data": {
"id": 61,
"title": "First"
},
"type": "like"
},
{
"data": {
"id": 62,
"title": "Seven"
},
"type": "like"
},
{
"data": {
"id": 103,
"title": "Third",
},
"type": "dislike"
},
{
"data": {
"id": 7,
"title": "Fifth",
},
"type": "dislike"
}
]
Multiple dictionaries with same type key are inside the list and I am trying to merge dictionaries into one list which have same keys.
I am trying to get like :-
[
{
"like": [
{
"id": 61,
"title": "First"},
{
"id": 62,
"title": "Second"
}
],
},
{
"dislike": [
{
"id": 103,
"title": "Third"
},
{
"id": 7,
"title": "Fifth"
}
],
},
]
I have tried using set() and union()
def comprehsion_method(list_dict):
converted_list = {
k : [d.get(k) for d in list_dict if k in d]
for k in set().union(*list_dict)
}
return converted_list
but This method merged all the data keys into one and all the type keys into one like :-
{
"data": [
{
"id":61,
"title": "First"
},
{
"id":62,
"title": "Second"
},
{
"id":103,
"title": "Third"
},
{
"id":7,
"title": "Seven"
},
],
"type": [
"like",
"like",
"dislike",
"dislike"
]
}
I have many times but it is still not working. Any help would be much Appreicated.
With comprehensions, especially complicated ones, it is best to start by writing out the explicit loop. In this case, you need something like:
new = {"like": [], "dislike": []}
for item in data:
if item["type"] == "like":
new["like"].append(item["data"])
else:
new["dislike"].append(item["data"])
print(new)
At this stage it is apparent that this function is trying to aggregate to a series of lists - something which comprehensions aren't designed to do. While it might be possible to convert it into a list comprehension, it will likely be relatively complex and less readable than the above code - so in this case I would leave it as is.

Iterating though nested JSON values with python

I want to be able to iterate through nested values in a JSON file and add them to a list.
For example, I want to find the values contained in each instance of Test below.
A= {"Tags": [
{
"Item":{
"Test":"mouse",
},
},
{
"Item":{
"Test":"dog",
},
},
{
"Item":{
"Test":"cat",
},
},
{
"Item":{
"Test":"dog",
},
}
]
}
I can select values individually like so:
print(A['Tags'][1]['Item']['Test'])
But I can't iterate over the entire JSON file.
This iterates over the whole and appends each value to a list.
output = list()
for tag in A['Tags']:
output.append(tag['Item']['Test'])
If you're worried about missing values, the following will correct for that.
output = list()
for tag in A['Tags']:
if item := tag.get('Item', dict()).get('Test'):
output.append(item)
Output:
['mouse', 'dog', 'cat', 'dog']
I have a simpler method: use the jsonpath package
You can learn jsonpath, which is very convenient, but the disadvantage is that it is slow
from jsonpath import jsonpath
A = {"Tags": [
{
"Item": {
"Test": "mouse",
},
},
{
"Item": {
"Test": "dog",
},
},
{
"Item": {
"Test": "cat",
},
},
{
"Item": {
"Test": "dog",
},
}
]
}
print(jsonpath(A, "$..Test"))
out
['mouse', 'dog', 'cat', 'dog']
for tag in A['Tags']:
print(tag['Item']['Test'])
A['Tags'] is just a list of objects/dictionary, which is referred by tag and then you can access any value inside the object via a key.

check if a property contains a specific value in a document with pymongo

I have a collection of documents that looks like this
{
"_id": "4",
"contacts": [
{
"email": "mail#mail.com",
"name": "A1",
"phone": "00",
"crashNotificationEnabled": false,
"locationShared": true,
"creationDate": ISODate("2020-10-19T15:19:04.498Z")
},
{
"email": "mail#mail.com",
"name": "AG2",
"phone": "00",
"crashNotificationEnabled": false,
"locationShared": false,
"creationDate": ISODate("2020-10-19T15:19:04.498Z")
}
],
"creationDate": ISODate("2020-10-19T15:19:04.498Z"),
"_class": ".model.UserContacts"
}
And i would like to iterate through all documents to check if either crashNotificationEnabled or locationShared is true and add +1 to a counter if its the case, im quite new to python and mongosql so i actually have a hard time trying to do that, i tried a lot of things but there is my last try :
def users_with_guardian_angel(mongoclient):
try:
mydb = mongoclient["main"]
userContacts = mydb["userContacts"]
users = userContacts.find()
for user in users:
result = userContacts.find_one({contacts : { $in: [true]}})
if result:
count_users = count_users + 1
print(f"{count_users} have at least one notificiation enabled")
But the result variable stays empty all the time, so if somebody could help me to accomplish what i want to do and tell what i did wrong here ?
Thanks !
Here's one way you could do it by letting the MongoDB server do all the work.
N.B.: This doesn't consider the possibility of multiple entries of the same user.
db.userContacts.aggregate([
{
"$unwind": "$contacts"
},
{
"$match": {
"$expr": {
"$or": [
"$contacts.crashNotificationEnabled",
"$contacts.locationShared"
]
}
}
},
{
"$count": "userCountWithNotificationsEnabled"
}
])
Try it on mongoplayground.net.
Example output:
[
{
"userCountWithNotificationsEnabled": 436
}
]

Convert multiple lines of string into a JSON based on a delimiter

I am literally lost with ideas on converting multiple lines of string into a JSON tree structure
So, I have multiple lines of string like below under a particular excel column:
/abc/a[2]/a/x[1]
/abc/a[2]/a/x[2]
Since the above strings contain the delimiter / , I could use them to create a parent-child relationship and convert them into a Python dictionary (or) JSON like below:
{
"tag": "abc",
"child": [
{
"tag": "a[2]",
"child": [
{
"tag": "a",
"child": [
{
"tag": "a",
"child": [
{
"tag": "x[1]"
},
{
"tag": "x[2]"
}
]
}
]
}
]
}
]
}
I am unable to come up with a logic for this part of my project since I need to look for the presence of [1],[2] and assign them to a common parent and this needs to be done in some recursive way that works for strings with any length. Please help me out with any code logic in Python or provide me with suggestions. Much appreciated !!
Additional Update:
Just wondering if it would also be possible to include other column's data along with the JSON structure.
For ex: If the excel contains the below three columns with 2 rows
tag
text
type
/abc/a[2]/a/x[1]
Hello
string
/abc/a[2]/a/x[2]
World
string
Along with the JSON from the original question, is it possible to add these other column information as key-value attributes (to the corresponding innermost child nesting) in the JSON like below.
These do not follow the same '/' delimiter format, hence I am unsure on approaching this..
{
"tag": "abc",
"child": [
{
"tag": "a[2]",
"child": [
{
"tag": "a",
"child": [
{
"tag": "a",
"child": [
{
"tag": "x[1]",
"text": "Hello",
"type": "string"
},
{
"tag": "x[2]",
"text": "World",
"type": "string"
}
]
}
]
}
]
}
]
}
P.S: I felt it would be appropriate to add the data to the innermost child to avoid information redundancy... Please feel free to suggest including these other column in any other appropriate way as well.
You can use recursion with collections.defaultdict:
import collections, json
def to_tree(d):
v = collections.defaultdict(list)
for [a, *b], *c in d:
v[a].append([b, *c])
return [{'tag':a, **({'child':to_tree(b)} if all(j for j, *_ in b) else dict(zip(['text', 'type'], b[0][-2:])))}
for a, b in v.items()]
col_data = [['/abc/a[2]/a/x[1]', 'Hello', 'string'], ['/abc/a[2]/a/x[2]', 'World', 'string']] #read in from your excel file
result = to_tree([[[*filter(None, a.split('/'))], b, c] for a, b, c in col_data])
print(json.dumps(result, indent=4))
Output:
[
{
"tag": "abc",
"child": [
{
"tag": "a[2]",
"child": [
{
"tag": "a",
"child": [
{
"tag": "x[1]",
"text": "Hello",
"type": "string"
},
{
"tag": "x[2]",
"text": "World",
"type": "string"
}
]
}
]
}
]
}
]
def to_dict(data, old_data=None):
json={}
if old_data!=None:
json["child"]=old_data
for row in data.split("\n"):
path=json
for element in row.strip("/").split("/"):
if not "child" in path:
path["child"]=[]
path=path["child"]
for path_el in path:
if element==path_el["tag"]:
path=path_el
break
else:
path.append({"tag":element})
path=path[-1]
return json["child"]
#tests:
column="""/abc/a[2]/a/x[1]
/abc/a[2]/a/x[2]"""
print(to_dict_2(column))
print(to_dict_2(column,[{'tag': 'abc', 'child': [{'tag': 'old entry'}]}]))

Get "path" of parent keys and indices in dictionary of nested dictionaries and lists

I am receiving a large json from Google Assistant and I want to retrieve some specific details from it. The json is the following:
{
"responseId": "************************",
"queryResult": {
"queryText": "actions_intent_DELIVERY_ADDRESS",
"action": "delivery",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"outputContexts": [
{
"name": "************************/agent/sessions/1527070836044/contexts/actions_capability_screen_output"
},
{
"name": "************************/agent/sessions/1527070836044/contexts/more",
"parameters": {
"polar": "no",
"polar.original": "No",
"cardinal": 2,
"cardinal.original": "2"
}
},
{
"name": "************************/agent/sessions/1527070836044/contexts/actions_capability_audio_output"
},
{
"name": "************************/agent/sessions/1527070836044/contexts/actions_capability_media_response_audio"
},
{
"name": "************************/agent/sessions/1527070836044/contexts/actions_intent_delivery_address",
"parameters": {
"DELIVERY_ADDRESS_VALUE": {
"userDecision": "ACCEPTED",
"#type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue",
"location": {
"postalAddress": {
"regionCode": "US",
"recipients": [
"Amazon"
],
"postalCode": "NY 10001",
"locality": "New York",
"addressLines": [
"450 West 33rd Street"
]
},
"phoneNumber": "+1 206-266-2992"
}
}
}
},
{
"name": "************************/agent/sessions/1527070836044/contexts/actions_capability_web_browser"
}
],
"intent": {
"name": "************************/agent/intents/86fb2293-7ae9-4bed-adeb-6dfe8797e5ff",
"displayName": "Delivery"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "en-gb"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"inputs": [
{
"rawInputs": [
{
"query": "450 West 33rd Street"
}
],
"arguments": [
{
"extension": {
"userDecision": "ACCEPTED",
"#type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue",
"location": {
"postalAddress": {
"regionCode": "US",
"recipients": [
"Amazon"
],
"postalCode": "NY 10001",
"locality": "New York",
"addressLines": [
"450 West 33rd Street"
]
},
"phoneNumber": "+1 206-266-2992"
}
},
"name": "DELIVERY_ADDRESS_VALUE"
}
],
"intent": "actions.intent.DELIVERY_ADDRESS"
}
],
"user": {
"lastSeen": "2018-05-23T10:20:25Z",
"locale": "en-GB",
"userId": "************************"
},
"conversation": {
"conversationId": "************************",
"type": "ACTIVE",
"conversationToken": "[\"more\"]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
}
]
}
},
"session": "************************/agent/sessions/1527070836044"
}
This large json returns amongst other things to my back-end the delivery address details of the user (here I use Amazon's NY locations details as an example). Therefore, I want to retrieve the location dictionary which is near the end of this large json. The location details appear also near the start of this json but I want to retrieve specifically the second location dictionary which is near the end of this large json.
For this reason, I had to read through this json by myself and manually test some possible "paths" of the location dictionary within this large json to find out finally that I had to write the following line to retrieve the second location dictionary:
location = json['originalDetectIntentRequest']['payload']['inputs'][0]['arguments'][0]['extension']['location']
Therefore, my question is the following: is there any concise way to retrieve automatically the "path" of the parent keys and indices of the second location dictionary within this large json?
Hence, I expect that the general format of the output from a function which does this for all the occurrences of the location dictionary in any json will be the following:
[["path" of first `location` dictionary], ["path" of second `location` dictionary], ["path" of third `location` dictionary], ...]
where for the json above it will be
[["path" of first `location` dictionary], ["path" of second `location` dictionary]]
as there are two occurrences of the location dictionary with
["path" of second `location` dictionary] = ['originalDetectIntentRequest', 'payload', 'inputs', 0, 'arguments', 0, 'extension', 'location']
I have in my mind relevant posts on StackOverflow (Python--Finding Parent Keys for a specific value in a nested dictionary) but I am not sure that these apply exactly to my problem since these are for parent keys in nested dictionaries whereas here I am talking about the parent keys and indices in dictionary with nested dictionaries and lists.
I solved this by using recursive search
# result and path should be outside of the scope of find_path to persist values during recursive calls to the function
result = []
path = []
from copy import copy
# i is the index of the list that dict_obj is part of
def find_path(dict_obj,key,i=None):
for k,v in dict_obj.items():
# add key to path
path.append(k)
if isinstance(v,dict):
# continue searching
find_path(v, key,i)
if isinstance(v,list):
# search through list of dictionaries
for i,item in enumerate(v):
# add the index of list that item dict is part of, to path
path.append(i)
if isinstance(item,dict):
# continue searching in item dict
find_path(item, key,i)
# if reached here, the last added index was incorrect, so removed
path.pop()
if k == key:
# add path to our result
result.append(copy(path))
# remove the key added in the first line
if path != []:
path.pop()
# default starting index is set to None
find_path(di,"location")
print(result)
# [['queryResult', 'outputContexts', 4, 'parameters', 'DELIVERY_ADDRESS_VALUE', 'location'], ['originalDetectIntentRequest', 'payload', 'inputs', 0, 'arguments', 0, 'extension', 'location']]

Categories

Resources