Reputation: 45
I have a nested JSON-file that looks like this:
[
{
"IsRecentlyVerified": true,
"AddressInfo": {
"Town": "Haarlem",
},
"Connections": [
{
"PowerKW": 17,
"Quantity": 1
}
],
"NumberOfPoints": 1,
},
{
"IsRecentlyVerified": true,
"AddressInfo": {
"Town": "Haarlem",
},
"Connections": [
{
"PowerKW": 17,
"Quantity": 1
},
{
"PowerKW": 17,
"Quantity": 1
}
],
"NumberOfPoints": 1,
}
]
As you can see, the list of this JSON-file consists of two dictionaries that each contains another list (= "Connections") that consists of at least one dictionary. In each dictionary of this JSON-file, I want to select all keys named "Quantity" to make a sum with its value (so in the example code above, I want to calculate that there are 3 Quantities in total).
Sometimes, the key "Quantity" is not always present, so that's why I used in
to check if it is present. I noticed that it now only finds the key "Quantity" when I mention the index, like this: if "Quantity" in ev_list[info]["Connections"][0]
def amountOfChargingStations():
totalAmountOfChargingPolesInCity = 0
for info in range(len(ev_list)):
if "Town" in ev_list[info]["AddressInfo"]:
if ev_list[info]["AddressInfo"]["Town"] == "Haarlem":
totalAmountOfChargingStationsInCity = totalAmountOfChargingStationsInCity + 1
if "Quantity" in ev_list[info]["Connections"][0]:
if ev_list[info]["Connections"]:
for pole in ev_list[info]["Connections"]:
totalAmountOfChargingPolesInCity = totalAmountOfChargingPolesInCity + pole["Quantity"]
else:
print("Can't find connection")
print("There are at least", totalAmountOfChargingPolesInCity, "charging poles available.")
polesAndStations = amountOfChargingStations()
The problem is that it now only uses the first dictionary of each "Connections"-list to make the sum. How can I select all keys named "Quantity" to make this sum, without knowing the total the amount of dictionaries in each "Connections"-list? (The total amount varies from 1 up to more than 10). Is there something like [0:end]
?
Upvotes: 1
Views: 91
Reputation: 36
as a oneliner:
total_quantity = sum([con['Quantity'] for dataset in data for con in dataset['Connections'] if 'Connections' in dataset.keys() and 'Quantity' in con.keys() ])
given data
is your imported json.
EDIT: sorry, did not read your code carefully enough.
actually you do not need to be so complicated with the for loop over a range, sounds like you are coming from another programming language. With
for info in ev_list
...
you already get the element itself and can change ev_list[info]
to info
.
Also did you get totalAmountOfChargingStationsInCity from somewhere else? It should return a 'referenced before assignment error' like this.
I am still a fan of oneliners and list comprehensions, so this would do the trick for me:
def amountOfChargingStations():
total_amount_of_charging_poles_in_city = 0
total_amount_of_charging_stations_in_city = 0
for info in ev_list:
if "Town" in info["AddressInfo"]:
if info["AddressInfo"]["Town"] == "Haarlem":
total_amount_of_charging_stations_in_city = total_amount_of_charging_stations_in_city + 1
total_amount_of_charging_poles_in_city += sum(
[con.get('Quantity', ) for con in info.get('Connections', [])])
print("There are at least", total_amount_of_charging_poles_in_city, "charging poles available.")
EDIT2: sorry, my mistake, changed the comprehension a bit. dictionary.get('key', 'default if key is not in dictionary') is a safer way to call something from a dictionary.
Upvotes: 1
Reputation: 3233
using jmespath
you can get sum as
import jmespath
print(sum(jmespath.search("[*].Connections[].Quantity", data), 0))
Upvotes: 1
Reputation: 26870
Here's a simple approach that, given the structure of your JSON as described, works as required:
quantity = 0
for d in json.loads(JDATA):
if (_list := d.get('Connections')):
for _d in _list:
quantity += _d.get('Quantity', 0)
print(quantity)
Output:
3
Upvotes: 1
Reputation: 195408
You can try recursion:
import json
def get_quantity(o):
if isinstance(o, dict):
if "Quantity" in o:
yield o["Quantity"]
for v in o.values():
yield from get_quantity(v)
elif isinstance(o, list):
for v in o:
yield from get_quantity(v)
with open("your_file.json", "r") as f_in:
data = json.load(f_in)
print(sum(get_quantity(data)))
Prints:
3
Upvotes: 1