Python3 - loop through list with mulitple dictionaries - python

sorry I am rather a beginner when it comes to python.
I have a list like this:
"list": [
{
"id": 12345,
"name": "test"
},
{
"id": 12453,
"value": "value1",
"field": "test",
}
]
When looping through several of such lists I want it to print the "name" key from the upper dictionary but only if the condition is met that "value": "value1", is present but this is in a different dictionary.
I tried with stuff like: if 'value' in event.keys():
but I cant manage to only print this "name" key if the other condition is met. any suggestions?

Below one way of doing it, it is going through all key/value of all dictionnaries so it's probably not efficient but will adapt to several possibility.
I don't know if name can be in the list several times, the below code will keep the last occurrence if it happens.
I made it a function so that you can use it easily on several similar lists. It returns None if the criteria was not met, the value of name if it was.
def get_valid_name(dict_list, target_value):
keep_name = False
current_name = None
for d in dict_list:
for key, val in d.items():
if key == "name":
current_name = val
elif key == "value" and val == target_value:
keep_name = True
return current_name if keep_name else None
for l in [original_list]:
result = get_valid_name(l, "value1")
if result is not None:
print(result)

Related

How to get a list of dict that each dict is coming from the same original dict with only one key removed?

My scenario:
I need to iterate through a nested json object, get return a list of json object, each has one key removed. And you don't know how the original data are structured.
As far as I go:
I wrote a recursion function to print every key value in the object. It works. But this is not what I want.
Define return:
This function gets a dict and returns a list of dict, each dict is a copy of the original dict after one key removed.
If the dict has 3 keys from the beginning, then I should get 3 dicts each has 1 key removed.
And yes if the key has nested value, they should be removed as well. For example if the key happens to be the root key, then it remains an empty dict.
Here's my code:
def iterate_keys(data: dict):
# This is as far as I can go
for key, value in data.items():
if type(value) in [dict, ]:
iterate_keys(value)
elif type(value) in [list, ]:
for item in value:
if type(item) in [dict]:
iterate_keys(item)
print(key, value)
# def what_i_really_want(data: dict) -> list:
# return [dict1, dict2, ...]
if __name__ == '__main__':
test_dict = {
"a": "a",
"c": {
"c1": [
{"c11": "c11"},
{"c12": "c12"},
]
},
}
iterate_keys(test_dict)
For the test_dict in the code, ideally it should return list dicts like blow.
result_should_be = [
{
# with "a" removed
"c": {
"c1": [
{"c11": "c11"},
{"c12": "c12"},
]
}
},
# with "c11" removed
{
"a": "a",
"c": {
"c1": [
{"c12": "c12"},
]
}
},
# with "c12" removed
{
"a": "a",
"c": {
"c1": [
{"c11": "c11"},
]
}
},
# with "c1" removed
{
"a": "a",
"c": {}
},
# with "c" removed
{
"a": "a"
},
]
At the end of the day, I'm creating a bunch of test cases.
Hope I made myself clear
I have really been struggling with this. Somehow I managed to solve it with two libraries.
The first one jsonpathgenerator gets me all the jsonpath of my original data. It orginally gave me all the 'leaf' item's jsonpath. So I changed the source code a little bit to get every key's jsonpath.
The second one jsonpath_ng let me filter a key with jsonpath.
And with a little bit data manipulation I got the result I was looking for.
This is for if someone ever run into the same situation as me.

How to a key recursively in a dictionary and return it's value

I have a nested dictionary like below
dictionary = {"name": "Stephen", "language": "English", "address": "13 Aust road", "teacher_info": [{"name": "Alan", "language": "Italian"}]}
I want to return the languages.
Output = ["English", "Italian"]
What have I tried
output = []
for i, j in dictionary.items():
if i == "language":
output.appened(j)
For things like this recursion is your friend. The following function will find keys called language and add their value to the list.
If any of the items in the dictionary is itself a dictionary we do the same thing. We concatenate the languages found in the nested dictionary to the list at the top level.
The base case for a dictionary without any languages is an empty list.
def get_languages(dictionary):
output = []
for key, value in dictionary.items():
if key == "language":
output.appened(value)
elif isinstance(value, dict):
output += get_languages(value)
return output

How to find the last matched key by comparing with list and dictionary

A list and dictionary is below
main_list = ["projecttype","emptype","Designation"]
sample = {"query": {
"emptype":["Manager"],"projecttype":["temp"],
"from": [
"0"
],
"q": [
""
],
"size": [
"4"
]
}}
How to find from the main_list which key is last "entered key" in sample dictionary
How to find from the main_list which key is first "entered key" in sample dictionary
In this particular scenario
"projecttype" is my output for last entered key which matches
emptype is my output for first entered key which matches
You can iterate through it and test if the keys are in your main_list. Save every key that is in main_list and after the for loop you will have the last entered key.
main_list = ["projecttype","emptype","Designation"]
sample = {
"query": {
"emptype": ["Manager"],
"projecttype": ["temp"],
"from": ["0"],
"q": [""],
"size": ["4"]
}
}
first = None
last = None
for key, value in sample['query'].items():
if key in main_list:
if first is None:
first = key
last = key
print('First:', first)
print('Last:', last)
You could do this in a cuple of lines and have the order of all the elements that are contained in your main_list as follow:
sample_query_keys = list(sample['query'].keys())
result = {sample_query_keys.index(main_key):main_key for main_key in main_list if main_key in sample_query_keys}
Then you can get the first and last item as follow:
print(result[0], result[len(result)-1])
Keep in mind that this will only work if the dictionary is ordered. That is only possible in Python 3.7 onwards. For previous versions, you would need to use OrderedDict.

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'])

Issues iterating through JSON list in Python?

I have a file with JSON data in it, like so:
{
"Results": [
{"Id": "001",
"Name": "Bob",
"Items": {
"Cars": "1",
"Books": "3",
"Phones": "1"}
},
{"Id": "002",
"Name": "Tom",
"Items": {
"Cars": "1",
"Books": "3",
"Phones": "1"}
},
{"Id": "003",
"Name": "Sally",
"Items": {
"Cars": "1",
"Books": "3",
"Phones": "1"}
}]
}
I can not figure out how to properly loop through the JSON. I would like to loop through the data and get a Name with the Cars for each member in the dataset. How can I accomplish this?
import json
with open('data.json') as data_file:
data = json.load(data_file)
print data["Results"][0]["Name"] # Gives me a name for the first entry
print data["Results"][0]["Items"]["Cars"] # Gives me the number of cars for the first entry
I have tried looping through them with:
for i in data["Results"]:
print data["Results"][i]["Name"]
But recieve an error:
TypeError: list indices must be integers, not dict
You are assuming that i is an index, but it is a dictionary, use:
for item in data["Results"]:
print item["Name"]
Quote from the for Statements:
The for statement in Python differs a bit from what you may be used to in C or Pascal. Rather than always iterating over an arithmetic progression of numbers (like in Pascal), or giving the user the ability to define both the iteration step and halting condition (as C), Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.
you are iterating through the dictionary not indexes so you should either use.
for item in data["Results"]:
print item["Name"]
or
for i in range(len(data["Results"])):
print data["Results"][i]["Name"]
The confusion is in how dictionaries and lists are used in iteration.
A dictionary will iterate over it's keys (which you use as indices to get corresponding values)
x = {"a":3, "b":4, "c":5}
for key in x: #same thing as using x.keys()
print(key,x[key])
for value in x.values():
print(value) #this is better if the keys are irrelevant
for key,value in x.items(): #this gives you both
print(key,value)
but the default behaviour of iterating over a list will give you the elements instead of the indices:
y = [1,2,3,4]
for i in range(len(y)): #iterate over the indices
print(i,y[i])
for item in y:
print(item) #doesn't keep track of indices
for i,item in enumerate(y): #this gives you both
print(i,item)
If you want to generalize your program to handle both types the same way you could use one of these functions:
def indices(obj):
if isinstance(obj,dict):
return obj.keys()
elif isinstance(obj,list):
return range(len(obj))
else:
raise TypeError("expected dict or list, got %r"%type(obj))
def values(obj):
if isinstance(obj,dict):
return obj.values()
elif isinstance(obj,list):
return obj
else:
raise TypeError("expected dict or list, got %r"%type(obj))
def enum(obj):
if isinstance(obj,dict):
return obj.items()
elif isinstance(obj,list):
return enumerate(obj)
else:
raise TypeError("expected dict or list, got %r"%type(obj))
this way if you, for example, later changed the json to store the results in a dict using the id as keys the program would still iterate through it the same way:
#data = <LOAD JSON>
for item in values(data["Results"]):
print(item["name"])
#or
for i in indices(data["Results"]):
print(data["Results"][i]["name"])
for json_data in data['Results']:
for attribute, value in json_data.iteritems():
print attribute, value # example usage

Categories

Resources