Updating dictionary values using zip() in python - python

I have 4 lists of floats which I have extracted from a JSON file. I have to modify the values in these 4 lists simultaneously, depending on the first list. I am using zip() to iterate over all the 4 lists, but I am unable to update the values in the original dictionary representing the JSON.
I need to check the sign of an element in first list, if it is negative, all the values in the 4 lists which have the same index as that element have to be zeroed out. The following code snippet contains some sample data:
{
"channels": [
{
"name": "TTZAR1e",
"samples": [
{
"data": [0.0996781, 0.0177724, -0.00566106],
"modifiers": [
{"data": [0.084338, 0.0103356, 0.010294], "type": "staterror"},
{"data": {"hi_data": [0.0996781, 0.0177724, -0.00566106], "lo_data": [0.0996781, 0.0177724, -0.00566106]}, "type": "histosys"}
],
"name": "conv"
}
]
}
]
}
And here's what I've tried so far:
import json
file = open("test1.json", 'r')
json_data = json.load(file)
for key, value in json_data.items():
for i in value:
for samp in i.get('samples'):
for mod in samp.get('modifiers'):
hi_list=[]
lo_list=[]
if(mod.get('type') == 'staterror'):
stat_list = mod.get('data')
if(mod.get('type') == 'histosys'):
hi_list = mod.get('data').get('hi_data')
lo_list = mod.get('data').get('lo_data')
for val, val2, val3, val4 in zip(samp.get('data'), hi_list, lo_list, stat_list):
if (val<0):
val,val2,val3,val4 = 0,0,0,0
When I print the JSON, I still get the original negative values. The final output I am working towards is something like the following:
{
"channels": [
{
"name": "TTZAR1e",
"samples": [
{
"data": [0.0996781, 0.0177724, 0],
"modifiers": [
{"data": [0.084338, 0.0103356, 0],"type": "staterror"},
{"data": {"hi_data": [0.0996781, 0.0177724, 0], "lo_data": [0.0996781, 0.0177724, 0]}, "type": "histosys"}
],
"name": "conv"
}
]
}
]
}
I would like to know how to update the values in the dictionary itself. Is there a way to implement this here?

zip() creates a list of tuples. These tuples do not share any memory with the original lists, meaning that you have no way of mutating the inputs to zip() using what it returns.
You should store references to the lists that you want to modify, and then modify them in-place. (I will note that you should seriously consider simplifying this code, as the high nesting depth makes this code hard to read and debug.) Here's a code snippet that does that:
for key, value in json_data.items():
for i in value:
for samp in i.get('samples'):
lists_to_modify = [samp.get('data')]
for mod in samp.get('modifiers'):
if(mod.get('type') == 'staterror'):
lists_to_modify.append(mod.get('data'))
if(mod.get('type') == 'histosys'):
lists_to_modify.append(mod.get('data').get('hi_data'))
lists_to_modify.append(mod.get('data').get('lo_data'))
for data_index in range(len(samp.get('data'))):
if samp.get('data')[data_index] < 0:
for list_to_modify in lists_to_modify:
list_to_modify[data_index] = 0

Related

How can I get the dates from this nested list in Python

My data contains nested lists and I am trying to create a list that contains only the date information from the second layer of nested lists.
"DateMap": {
"2020-12-04:0": {
"55.0": [
{
}]},
"2020-12-11:7": {
"60.0": [
{
}]}
}
I want to get a list that is like this mylist = ["2020-12-04:0", "2020-12-11:7"]
I have looked into using regex and list comprehensions and this is the expression I have found to match the dates ^\d{4}-\d\d-\d\d:\d\d?$
How can I make this work?
Use the function .keys(). This just gets all the keys of a dictionary, which is exactly what you're looking for. If DateMap is inside a dictionary, say dic, just do the same thing for dic["DateMap"].
DateMap = {
"2020-12-04:0": {
"55.0": [
{
}]},
"2020-12-11:7": {
"60.0": [
{
}]}
}
mylist = DateMap.keys()
# mylist = list(DateMap.keys()) for Python 3
print(mylist)
# Prints ['2020-12-04:0', '2020-12-11:7']

python: a list comprehension over a list of dictionaries of list of dictionary items

I know this is a worst title but let me explain the question by sample. My data is:
data = [
{
"subdata": [ # subdata various number of dictionaries of same keys, including "ext_id", ...
{
"ext_id": "12345", # ... but of different values
...
},
{
"ext_id": "54321",
...
}
],
...
},
... # and many other dictionary items with "subdata", which in turn contains
# a list of dictionaries containing "ext_id" and corresponding values
]
my goal is make a list of the pair of "ext_id"s in "subdata", i.e.
goal = [
("12345", "54321"),
(...)
]
I know a for-loop is okay for this goal, but wondering if a list comprehension is possible? I tried this:
goal = [x["ext_id"] for y in data for x in y["subdata"]]
and get a flattened version of goal ["12345", "54321", ...] rather than a 2-D list.
Any advices are appreciated.
If you have a data structure like this:
data = [
{
"subdata": [
{
"ext_id": "12345",
},
{
"ext_id": "54321",
}
],
},
{
"subdata": [
{
"ext_id": "98765",
},
{
"ext_id": "56789",
}
],
}
]
Then to get the output that you want, you could use list comprehension (and a generator comprehension too) as follows:
goal = [tuple(dict_['ext_id'] for dict_ in subdata['subdata']) for subdata in data ]
goal will contain:
[('12345', '54321'), ('98765', '56789')]
Yes you can use list comprehension here. Following code will give you your desired results
[tuple(sub_dict.get('ext_id') for sub_dict in dictionary.get('subdata')) for dictionary in data]

Creating a list from data to include multiple entries then Iterate through list to return one string

What I have currently
I want to create a list from this data set to only include the name values, but have them grouped by each 'issue', so I then can iterate through this list and return one value based on priority.
{
"issues": [
{
"fields": {
"components": [],
"customfield_1": null,
"customfield_2": null
}
},
{
"fields": {
"components": [
{
"name": "Testing"
}
],
"customfield_1": null,
"customfield_2": null
}
},
{
"key": "3",
"fields": {
"components": [
{
"name": "Documentation"
},
{
"name": "Manufacturing"
}
],
"customfield_1": null,
"customfield_2": null
}
}
]
}
I want the output to look something like this:
['null', 'testing', ('Documentation', 'Manufacturing')]
I was able to accomplish this by the following code:
(sorry about the formatting, not sure how to make this looks better without having it on one line)
list((
'null' if len(item['fields']['components'])== 0
else
item['fields']['components'][0]['name']) if len(item['fields']['components'])==1
else
(item['fields']['components'][0]['name']), item['fields']['components'][1]['name'])))
for item in data['issues'])
The Problem
Now I need to have the value ("Documentation", "Manufacturing") from the above output to return only 1 component based on priority.
I think I need to iterate through something like ['Documentation', 'Testing', 'Manufacturing"]
so when it hits, lets say 'Documentation', it stops and returns only 'Documentation'. (this list is specific for priority and is in order of highest to lowest priority)
I want the final list to be ['null', 'Testing', 'Documentation']
I do not need the others to be changed, just the entry with multiple values.
How about the code below? I'm basically indexing the priority list and taking the minimum of it (since we're looking at the beginning to be of highest priority). We can switch this to max if the priority list ever changes.
Try this:
import json
with open("file.json") as f:
data = json.load(f)
result = []
priority = ['Documentation', 'Testing', 'Manufacturing']
for issue_dict in data['issues']:
if len(issue_dict["fields"]["components"]) == 0:
result.append([('null', 0)])
else: # Can support arbitrary number of custom fields
result.append([(list(name_dict.values())[0], priority.index(list(name_dict.values())[0])) for name_dict in issue_dict["fields"]["components"]])
print(result)
# [[('null', 0)], [('Testing', 1)], [('Documentation', 0), ('Manufacturing', 2)]]
result = [min(item, key= lambda x: x[1])[0] for item in result]
print(result)
#['null', 'Testing', 'Documentation']
For the nested lists: if the length is 1, then min will simply take the only choice obviously. For the others, we find the minimum index aka highest priority.
I've included some print statements strictly for debugging and for you to see if it makes sense. Hope this helps.
So i ended up doing it this way:
creating a function that will look if any "components" are in the given list, and will return and stop the iteration when the given component is found
def _define_component(multiple_component_list):
for components in ['Documentation', 'Testing', 'Manufacturing']:
if components in multiple_component_list:
return components
return 'Unknown'
and calling the function in my list comprehension with the expression i used when the length > 1 as the argument (same as original code except after the last 'else' statement)
list(('Unknown' if len(item['fields']['components']) == 0 else
item['fields']['components'][0]['name'] if len(
item['fields']['components']) == 1 else _define_component(
[item['fields']['components'][0]['name'],
item['fields']['components'][1]['name']]))for item in data['issues'])

Merge/Concatenate two dictionaries (/tuples) with same keys python

I have two json objects represented as a dictionary and I want to concatenate both into one and the last will be a json.
At the moment I have:
obj1 = {
"FS":11440000,
"BW":76000000,
"Gain":62,
"Fc":70000000,
"real":[ 4,2,3,],
"imag":[1,1,3,],
}
obj2 = {
"FS":61440000,
"BW":56000000,
"Gain":62,
"Fc":80000000,
"real":[ 1,2,3,],
"imag":[1,2,3,],
}
I want to have:
[
{
[
{
"FS":61440000,
"BW":56000000,
"Gain":62,
"Fc":70000000,
"real":[ 1,2,3,],
"imag":[1,2,3,],
},
{
"FS":61440000,
"BW":56000000,
"N":8192,
"Gain":62,
"Fc":80000000,
"real":[ 1,2,3,],
"imag":[1,2,3,],
}
],
"ts":1231234165234,
"scale":[10000,-45],
"N":8192,
},
]
How to join obj1 + obj2 and remain the keys and not update them? I need all of them as you can see the final output I'm trying to create.
After concatenating obj1 and obj2 into one I need to add 3 more keys.
I'm using python 3.6.
The dict output you expect is badly formatted, so you will never be able to make it. (dicts needs key for each value - even if value can be list).
foo = {"foo": "value"}
bar = {"bar": "value"}
data = {"ts": "...", "scale": [10000, -45], "N": 8192, "data": [foo, bar]}
Would gives you a dict where you can access data via data['data']

How to load a .json file as a dictionary

I want to save the information from a .json file as a dictionary containing other dictionaries. I attempted, but, when I try to access the first key, it is a string, rather than another dictionary. Here is my code:
with open('matches1.json', 'r') as json_file:
match_histories = json.load(json_file)
print(match_histories[key]['matches'])
for i in range(6):
print(match_histories[key][i])
The first print results in an error, the second results in 'matches'.
The file I want to load can be downloaded but the structure is basically:
{
"matches": [
{
"matchId": 1778839570,
"region": "NA",
"platformId": "NA1",
"matchMode": "CLASSIC",
"matchType": "MATCHED_GAME",
"matchCreation": 1427867835805,
"matchDuration": 3424,
"queueType": "RANKED_SOLO_5x5",
"mapId": 11,
"season": "SEASON2015",
"matchVersion": "5.6.0.194",
"participants": [
// more dictionaries
],
"participantIdentities": [
// more dictionaries
],
"teams": [
// more dictionaries
],
"timeline": {
"frames": [
// many frame dictionaries
],
"frameInterval": 60000
}
},
// more dictionaries
]
}
I saved it as matches1.json in the same directory as my code.
I have also tried putting
match_histories={}
before my other code, but that didn't help either.
How can I save this .json file as a dictionary containing dictionaries?
match_histories is a dictionary with one key, matches. The value is a list of dictionaries; loop over that list:
for match in match_histories['matches']:
print(match['matchId'])
Warning: the match objects are themselves large dictionaries.

Categories

Resources