I am trying to delete items, based upon a lookup table i iterate through inside my python dictionary, but am not able to delete the values.
This post depends on python 3.8 to work with.
inEvent = {
"event_data": {
"event_name": "Test",
"station_id": "Station1",
"serial_no": "1234",
},
"tests": [
{
"name": "Temperature from Sensor 1",
"status": "Passed",
"value": "21.0",
"limits": [],
"units": "°C",
},
{
"name": "Power Measurement CH1",
"status": "Passed",
"value": "30.9",
"limits": [],
"units": "W",
},
{
"name": "Slope Check: Measured Slope CH1",
"status": "Passed",
"value": "1234.5678",
"limits": {"low": "0", "high": None},
"units": [],
},
{
"name": "Slope Check: Measured Slope CH2",
"status": "Passed",
"value": "-1",
"limits": [],
"units": [],
},
],
"plots": [],
}
while iterating over my dictionary i replace matching names, but in rare cases i want to delete the complete matching test entry. for e.g.{"name": "Slope Check: Measured Slope CH1", "status":"Passed","value": "1234.5678","limits": {"low": "0", "high": None},"units": [],} should be deleted
for t in list(inEvent['tests']):
eventName = t['name']
for row in self.LookUpTable.itertuples(index=False): # own lookuptable excel file
if eventName == row[4] and not pd.isnull(row[5]):
t['name'] = row[5]
break
elif eventName == row[4] and pd.isnull(row[5]):
print(inEvent)
inEvent['tests'].pop(t)
break
I recommend using a nested loop for this. You can do this by looping through all of the keys and values in the dictionary and then loop through all of the keys and values in the nested dictionaries. You can then use an if statement to find the key in teh dictionary that you want to delete. Here is a simple outline of code that you can use (if this does not work then I recommend googling exactly what the issue is and looking further into it):
for key, value in dict.items():
for k, v in k.items():
if v == something:
del key[k]
Related
I'm trying to parse through a JSON file and return results only if specific key exists. Here is the example of the JSON:
"phone_numbers": [
{
"id": "123456",
"number": "+11234567890",
"source": "external",
"status": "available",
"number_type": "toll",
"capability": [
"incoming",
"outgoing"
],
"location": "United States",
"assignee": {
"id": "1234",
"name": "John Smith",
"extension_number": 7890,
"type": "user"
},
"site": {
"id": "123456",
"name": "COPQ"
},
"emergency_address": {
"country": "US",
"address_line1": "Testing",
"address_line2": "Testing",
"city": "Testing",
"state_code": "PA",
"zip": "19428"
},
"emergency_address_status": 1
},
So for above I only want to return record if key 'assignee' is present, if not just bypass it. For now I'm just trying to count how many records have 'assignee' but can't get it to work. Here is what I'm using:
counter = 0
for i in user_data['phone_numbers']:
if i['assignee']:
counter += 1
print(counter)
You can use in keyword. The in keyword can also be used to check if a value is present in a sequence.
For example,
colors = ["red", "blue", "green"]
print("red" in colors) # True
The solution of your problem is as below-
records = []
for d in user_data["phone_numbers"]:
if "assignee" in d:
records.append(d)
print(len(records))
trying to count how many records have 'assignee'
You can use a generator expression to get that count
sum(1 for p in data["phone_numbers"] if "assignee" in p)
To get a list of all numbers with assignee keys, then a list-comprehension
assignees = [p in data["phone_numbers"] if "assignee" in p]
I have this sample.json file with me:
{
"details":[
{
"name": "",
"class": "4",
"marks": "72.6"
},
{
"name": "David",
"class": "",
"marks": "78.2"
},
{
"name": "Emily",
"class": "4",
"marks": ""
}
]
}
As you can see for the first one; "name" is string datatype is actually empty.
For the second one; "class" with integer datatype is empty.
And for the third one; "marks" with float datatype is empty.
Now my task is;
to find the fields which are empty, if string is empty replace it with "BLANK", if integer is empty replace it with 0, and if float is empty replace it with 0.0
P.S: I'm doing this with Python like this:
import json
path = open('D:\github repo\python\sample.json')
df = json.load(path)
for i in df["details"]:
print(i["name"])
Also make sure that I don't want to hard-code the values. Coz here if we see there are only 3 fields(name, class, marks) but what if I have more that 3. Then what? How will I find which fields are empty or not?
Like you see here:
{
"code": "AAA",
"lat": "-17.3595",
"lon": "-145.494",
"name": "Anaa Airport",
"city": "Anaa",
"state": "Tuamotu-Gambier",
"country": "French Polynesia",
"woeid": "12512819",
"tz": "Pacific\/Midway",
"phone": "",
"type": "Airports",
"email": "",
"url": "",
"runway_length": "4921",
"elev": "7",
"icao": "NTGA",
"direct_flights": "2",
"carriers": "1"
},
This is just one block, I've N-number of blocks like this. That's why I can't hard_code the values right?
Can anybody help me with it!
Thank You so much!
Since the type info isn't available anywhere programmatically, and there seem to be only three hard-coded fields, I'd just check each of them explicitly.
Short-circuiting with the or operator would even allow you to achieve this fairly elegantly:
for d in df['details']:
d['name'] = d['name'] or 'BLANK'
d['class'] = d['class'] or '0'
d['marks'] = d['marks'] or '0.0'
You could check whether the string is empty with a simple if statement like so.
if not i['name'] == ""
Alternatively, you could also do
if not i['name']
The second if statement makes use of falsy and truthy values in Python. Here's a link to read more about it
You could create a dictionary empty_replacements mapping each key to its corresponding desired empty value:
import json
sample_json = {
"details": [
{
"name": "",
"class": "4",
"marks": "72.6"
},
{
"name": "David",
"class": "",
"marks": "78.2"
},
{
"name": "Emily",
"class": "4",
"marks": ""
}
]
}
empty_replacements = {"name": "BLANK", "class": "0", "marks": "0.0"}
sample_json["details"] = [{
k: v if v else empty_replacements[k]
for k, v in d.items()
} for d in sample_json["details"]]
print('sample_json after replacements: ')
print(json.dumps(
sample_json,
sort_keys=False,
indent=4,
))
Output:
sample_json after replacements:
{
"details": [
{
"name": "BLANK",
"class": "4",
"marks": "72.6"
},
{
"name": "David",
"class": "0",
"marks": "78.2"
},
{
"name": "Emily",
"class": "4",
"marks": "0.0"
}
]
}
I 'm assuming by the dictionary which you provided that marks & class are stored as String.
li=[]
for d in df["details"]:
for k,v in d.items():
if (v==''):
if (k=='name'):
d[k]="BLANK"
elif (k=='class') :
d[k]='0'
elif (k=='marks'):
d[k]='0.0'
li.append(d)
df['details']=li
How can I call a specific list with items in a dictionary? I want to use the key name, and output Richmond, in the station list. A tutorial I was using is outdated, so the best I could manage was this loop that printed the keys and items:
for key, value in data.items():
print(key, value)
That revealed the two outermost keys (?xml and root), but there are nested dictionaries I would like to access.
What I would like:
for item in data['station']
print(item['name'])
>>> Richmond
Instead I get KeyError with station. Seeing as how ?xml and root are the keys identified with the loop, I'm presuming I need a nested loop, first going through the root key, and then accessing station, and then using the key name to print Richmond.
The API result:
{
"?xml": {
"#version": "1.0",
"#encoding": "utf-8"
},
"root": {
"#id": "1",
"uri": {
"#cdata-section": "http://api.bart.gov/api/etd.aspx?cmd=etd&orig=RICH&json=y"
},
"date": "10/14/2017",
"time": "07:50:17 PM PDT",
"station": [{
"name": "Richmond",
"abbr": "RICH",
"etd": [{
"destination": "Warm Springs",
"abbreviation": "WARM",
"limited": "0",
"estimate": [{
"minutes": "4",
"platform": "2",
"direction": "South",
"length": "6",
"color": "ORANGE",
"hexcolor": "#ff9933",
"bikeflag": "1",
"delay": "0"
}, {
"minutes": "24",
"platform": "2",
"direction": "South",
"length": "6",
"color": "ORANGE",
"hexcolor": "#ff9933",
"bikeflag": "1",
"delay": "0"
}]
}]
}],
"message": ""
}
}
How do you pull, split, and append an array inside a dictionary inside a dictionary?
This is the data I've got:
data = {
"Event":{
"distribution":"0",
"orgc":"Oxygen",
"Attribute": [{
"type":"ip-dst",
"category":"Network activity",
"to_ids":"true",
"distribution":"3",
"value":["1.1.1.1","2.2.2.2"]
}, {
"type":"url",
"category":"Network activity",
"to_ids":"true",
"distribution":"3",
"value":["msn.com","google.com"]
}]
}
}
This is what I need --
{
"Event": {
"distribution": "0",
"orgc": "Oxygen",
"Attribute": [{
"type": "ip-dst",
"category": "Network activity",
"to_ids": "true",
"distribution": "3",
"value": "1.1.1.1"
}, {
"type": "ip-dst",
"category": "Network activity",
"to_ids": "true",
"distribution": "3",
"value": "2.2.2.2"
}, {
"type": "url",
"category": "Network activity",
"to_ids": "true",
"distribution": "3",
"value": "msn.com"
}, {
"type": "url",
"category": "Network activity",
"to_ids": "true",
"distribution": "3",
"value": "google.com"
}
}
}
Here is where I was just playing around with it and totally lost!!
for item in data["Event"]["Attribute"]:
if "type":"ip-dst" and len("value")>1:
if 'ip-dst' in item["type"] and len(item["value"])>1:
for item in item["value"]:
...and totally lost
How about this?
#get reference to attribute dict
attributes = data["Event"]["Attribute"]
#in the event dictionary, replace it with an empty list
data["Event"]["Attribute"] = []
for attribute in attributes:
for value in attribute["value"]:
#for every value in every attribute, copy that attribute
new_attr = attribute.copy()
#set the value to that value
new_attr["value"] = value
#and append it to the attribute list
data["Event"]["Attribute"].append(new_attr)
This will work with the data structure you've shown, but not necessarily with all kinds of nested data, since we do a shallow copy of the attribute. That will mean that you have to make sure that apart from the "value" list, it only contains atomic values like numbers, strings, or booleans. The values list may contain nested structures, since we're only moving references there.
I'm have been struggling with understanding the reason for the following Json parsing issue, I have tried many combinations to access the 'val' item value but I have hit a brick wall.
I have used the code below successfully on 'similar' Json style data, but I dont have the knowledge to craft this approach to the data below.
All advice gratefully accepted.
result = xmltodict.parse(my_read)
result = result['REPORT']['REPORT_BODY']
result =json.dumps(result, indent=1)
print(result)
{
"PAGE": [
{
"D-ROW": [
{
"#num": "1",
"type": "wew",
"val": ".000"
},
{
"#num": "2",
"type": "wew",
"val": ".000"
}
]
},
{
"D-ROW": [
{
"#num": "26",
"type": "wew",
"val": ".000"
},
{
"#num": "27",
"type": "wew",
"val": ".000"
},
{
"#num": "28",
"type": "wew",
"val": ".000"
}
]
}
]
}
for item in json.loads(json_data):
print(item['PAGE']['D-ROW']['val']
error string indices must be integers
item['PAGE'] contains a list, so you cannot index it with 'D-ROW'. If your json-loaded data is in a variable data you could use:
for page in data['PAGE']:
for drow in page['D-ROW']:
print drow['val']
The first thing should notice, based on your JSON structure is that it's a dict {"PAGE": [...], ...}, so when you use json.loads() on it, you'll get a dict too
In this for loop, your item iterator actually refers to the key from the dict
for item in json.loads(json_data):
print(item['PAGE']['D-ROW']['val']
Here's a simpler example easier to follow
>>> for key in json.loads('{"a": "a-value", "b": "b-value"}'):
... print(key)
...
a
b
error string indices must be integers
So you can guess that in your loop item would refer to the key "PAGE", and you can't index that string with ['D-ROW'] ("PAGE"['D-ROW'] doesn't make sense, hence your error)
Key/values in the for loop
To get items if you use the loop below, item becomes a tuple of (key, value)
for item in json.loads(json_data).items():
print(item)
You can also expand the key, value like this
>>> for key, value in json.loads('{"a": "a-value", "b": "b-value"}').items():
... print("key is {} value is {}".format(key, value))
...
key is a value is a-value
key is b value is b-value
Your JSON should not include quotes around values with numbers. For example, change
"D-ROW": [
{
"#num": "1",
"type": "wew",
"val": ".000"
},
to
"D-ROW": [
{
"#num": 1, // Key requires quotes, Value omits quotes if number
"type": "wew",
"val": 0.000
},
"D-ROW": [
{
"#num": "26",
"type": "wew",
"val": ".000"
},
{
"#num": "27",
"type": "wew",
"val": ".000"
},
{
"#num": "28",
"type": "wew",
"val": ".000"
}
D-ROW key contains a list, not a dict.
You should change
print(item['PAGE']['D-ROW']['val']
to
print([_item['val'] for _item in item['PAGE']['D-ROW']])
to iterate over the list which contains you dicts.