my python code is about generating a sequence number from a dict keys, and my dict keys are defined with a range using cycle package in itertools module.
working example:
from itertools import cycle
e = {'Apple': cycle(range(1,999)),'Orange': cycle(range(1,999)),'Banana': cycle(range(1,999))}
def SequenceNum(f):
return f'{next(e[f])}'.zfill(3)
X = SequenceNum('Apple')
print(X)
output
001 --> it keeps incrementing in the range specified above in dict `e`
Challenge:
My requirement is to convert this dict of e into a json file. So it will load keys and values by parsing json file.
cat test.json
{
"DATA": {
"Apple": "cycle(range(1,999))",
"Orange": "cycle(range(1,999))",
"Banana": "cycle(range(1,999))"
}
}
(i had to put the dict values inside double quotes to avoid json file loading error.)
code
import json
from itertools import cycle
with open('test.json') as f:
FromJson = json.load(f)
d = FromJson['DATA']
print(d)
def SequenceNum(f):
return f'{next(d[f])}'.zfill(3)
X = SequenceNum('Apple')
i = 1
while i <= 10:
print(i, SequenceNum('Apple'))
i += 1
here new dict is d that loads json file and it will load the values in single quotes.
output
{'Apple': 'cycle(range(1,999))', 'Orange': 'cycle(range(1,999))', 'Banana': 'cycle(range(1,999))'} #THIS IS OUTPUT of 'd' after loading json file
Traceback (most recent call last):
File "c:\Users\chandu\Documents\test.py", line 14, in <module>
print(i, SequenceNum('Apple'))
File "c:\Users\chandu\Documents\test.py", line 12, in SequenceNum
return f'{next(d[f])}'.zfill(3)
TypeError: 'str' object is not an iterator
it is giving error because my dict values are not properly iterable by cycle itertools modules, since they are in quotes. i dont know if there is any other cause for this error.
please help to resolve this error,
Thanks in advance.
If you are sure what each value is, you can do eval with care:
def SequenceNum(f):
return f'{next(eval(d[f]))}'.zfill(3)
Note this is very dangerous to use, because eval evaluates anything that is passed into it and can cause harm.
This also will always fetch first value from iterator as it is evaluated new everytime. To solve, you can:
def SequenceNum(f):
return eval(d[f])
i = 1
seq_iter = SequenceNum('Apple')
while i <= 10:
print(i, f'{next(seq_iter)}'.zfill(3))
i += 1
Related
I am trying to access a value in a json file using python. In the imgur link, the value I am trying to access is the "NUM" nested in "args". My main logic is reading in the JSON file, then using pandas to normalize the json.I have tried using .loc to try and find 'args' but I need help with another way or option.
[1]: https://i.stack.imgur.com/n6hOg.png
Here is my code snippet along with the terminal error I am getting
def readInJSON(json):
df = pandas.json_normalize(json)
goto_rows = [i for i in df.loc[df['mnemonic'] == 'PLD_CCD_EXPOSE_CLOSED'].index]
commandDates = list(df['utc_time'])
numIDs = list(df['args']) #tried using list typing
print(type(df['args'])) #couldnt get a typing from it either
args = df['args'] #tried just using it like a regular list
args = [i for i in df.loc[df['args']]] #tried using .loc from pandas as well
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pandas/core/frame.py", line 3505, in getitem
indexer = self.columns.get_loc(key)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3623, in get_loc
raise KeyError(key) from err
KeyError: 'args'
This is how you can access value of NUM:
import json
file = open('data.json')
data = json.load(file)
NUM = data[1]["args"]["NUM"]
# NUM = 20.0
file.close()
The JSON structure appears to be a list of dictionaries. Those dictionaries may or may not have a 'args' key. The value associated with 'args' is expected to be a dictionary. That dictionary may contains a 'NUM' key. If 'NUM' exists, append its value to a list. Return the list.
def readInJSON(json):
numvals = []
for d in json:
if (args := d.get('args')):
if isinstance(args, dict) and (num := args.get('NUM')):
numvals.append(num)
return numvals
A better approach might be to write the function so that it handles the input JSON file like this:
import json
def readInJSON(filename):
with open(filename) as jdata:
numvals = []
for d in json.load(jdata):
if (args := d.get('args')):
if isinstance(args, dict) and (num := args.get('NUM')):
numvals.append(num)
return numvals
I have this Json file, and I want to get the "navn" out with a iterating.
I need it to print:
Traktor
Bil and nothing else, how do I do that ?
[
{"navn": "Traktor", "år": 10, "købspris": 10000},
{"navn": "Bil", "år": 20, "købspris": 100000},
{},
{}
]
So far I have this idea
I know I need to import json file, and iterating through it but every time it gives me a error... I have tried searching the whole wide web and nothing came up
my code so far:
import json
def main():
f = open("/Users/maltheschroderjakobsen/Desktop/coding/test/mat.json",)
f = json.load(f)
for key in f["navn"]:
print (key)
main()
But every time I try anything else it gives me a error
f seems to be a list, not a dictionary:
for dct in f:
if "navn" in dct: # the elements are dicts!
print(dct["navn"])
It's because some dicts have no key navn. Use dict.get instead:
import json
def main():
file = open("/Users/maltheschroderjakobsen/Desktop/coding/test/mat.json",)
data = json.load(file)
for dct in data:
print(dct.get("navn", ""))
main()
So long as the JSON only has dicts, you can do:
js='''\
[
{"navn": "Traktor", "år": 10, "købspris": 10000},
{"navn": "Bil", "år": 20, "købspris": 100000},
{},
{}
]'''
import json
>>> [e['navn'] for e in json.loads(js) if e.get('navn', '')]
['Traktor', 'Bil']
JSON can also have other datatypes such as lists or numeral. If there is a possibility of something other than a dict in the JSON, you can do:
[e['navn'] for e in json.loads(js) if isinstance(e, dict) and e.get('navn', '')]
Is any way to load JSON code into the recursive defaultdict to avoid KeyError, using Python 2.7?
For example:
from __future__ import print_function
from collections import defaultdict
import json
S = '{"a": [{"b": "TEST1", "p": "TEST2"}, {"b": "TEST3", "p": "TEST4"}]}'
d = json.loads(S)
nd = lambda: defaultdict(nd)
ni = nd()
print('1: ', ni['a'][0]['b'])
ni.update(d)
print('2: ', ni['a'][0]['b'])
print('3: ', ni['a'][1]['p'])
print('4: ', ni['a'][1]['c'])
Result
1: defaultdict(<function <lambda> at 0x0266F530>, {})
2: TEST1
3: TEST4
Traceback (most recent call last):
File "C:/...", line 16, in <module>
print('4: ', ni['a'][1]['c'])
KeyError: 'c'
It looks like after ni.update(d) ni works as dict, and not like recursive defaultdict. Is any way to add dict into a recursive defaultdict and keep its properties?
I would expect result on the step 4 similar to the following:
4: defaultdict(<function <lambda> at 0x0266F530>, {})
It's not enough to create a recursive dict. You have to load the JSON object into your dict recursively.
What happens in your code is that ni['a'] is a normal dict, not a dict of type nd. When you run ni.update(d), update isn't clever enough to traverse d, writing objects on each level into objects of similar type. Instead, it just copies the first-level values and keys of d into ni. The first-level values are just ordinary dicts or whatever.
To initialize ni correctly, you need to write a recursive function which determines whether each value is a dict, array or scalar. If it's a dict, it has to call nd, and then fill the result with values for which it will act in the same recursive way.
OR, you can use the argument object_hook to json.loads. See https://docs.python.org/2/library/json.html#json.load for details. Whatever function you pass here will be called on each dict created at any level of parsing. So the function
def defaultdict_from_dict(d):
nd = lambda: defaultdict(nd)
ni = nd()
ni.update(d)
return ni
or something similar would probably do the trick for you.
Apologies in advance for this being such a newbie question. I'm just beginning to write python and i've been having some confusion around popping values from nested dictionaries/lists so i appreciate any help!
I have this sample json data:
{ "scans": [
{ "status": "completed", "starttime": "20150803T000000", "id":533},
{ "status": "completed", "starttime": "20150803T000000", "id":539}
] }
i'd like to pop the 'id' out of the "scans" key.
def listscans():
response = requests.get(scansurl + "scans", headers=headers, verify=False)
json_data = json.loads(response.text)
print json.dumps(json_data['scans']['id'], indent=2)
doesnt seem to be working because the nested key/values are inside of a list. i.e.
>>> print json.dumps(json_data['scans']['id'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str
can anyone point me in the right direction to get this to work? my longterm goal with this is to create a for-loop that places all of the id's into another dictionary or list that i can use for another function.
json_data['scans'] returns a list of dicts, you are trying to index the list using a str i.e []["id"] which fails for obvious reasons so you need to use the index to get each subelement:
print json_data['scans'][0]['id'] # -> first dict
print json_data['scans'][1]['id'] # -> second dict
Or to see all the id's iterate over the list of dicts returned using json_data["scans"]:
for dct in json_data["scans"]:
print(dct["id"])
To save append to a list:
all_ids = []
for dct in json_data["scans"]:
all_ids.append(dct["id"])
Or use a list comp:
all_ids = [dct["id"] for dct in json_data["scans"]]
If there is a chance the key id might not be in every dict, use in to check before you access:
all_ids = [dct["id"] for dct in json_data["scans"] if "id" in dct]
Here how can you iterate over the items and extract all ids:
json_data = ...
ids = []
for scan in json_data['scans']:
id = scan.pop('id')
# you can use get instead of pop
# then your initial data would not be changed,
# but you'll still have the ids
# id = scan.get('id')
ids.append();
This approach will work too:
ids = [item.pop('id') for item in json_data['scans']]
I am trying to compare values of key "rrname" in a json format file ,jadata dic (Each line is a dictionary) with keys of dictionary d which is already loaded in memory.
Here is my code:
import simplejson
ap = '/data/data/2014/A.1/ap.txt'
ddb = '/data/data/2014/A.1/test'
d={}
f = open(ap,'r')
g = open(ddb,'r')
for line in f:
domain,bl_date= line.split('|')
d[domain]=bl_date
for line in g:
line=line.strip('')
try:
jdata = simplejson.loads(line)
if jdata.get('rrname') == d.keys():
print rrname
except:
raise
here is my ddb file :
{"rrname": "bba186684.alshamil.net.ae.", "time_last": 1389295255, "time_first": 1389241418, }
{"rrname": "bba186686.alshamil.net.ae.", "time_last": 1390910891, "time_first": 1390910891}
{"rrname": "0001ewm.rcomhost.com", "time_last": 1390147425, "time_first": 1390124988}
here is ap file:
0001elk.rcomhost.com|1391726703
0001ewm.rcomhost.com|1393472522
0001qz6.wcomhost.com|1399977648
when I run this code, it cannot find the similarities, although there is. Can somebody help me with this?
jdata.get('rrname') == d.keys()
will always fail -- the single entry on the left of the == won't equal all entries on the right as you're asking.
Rather, check whether:
jdata.get('rrname') in d
The in operator looks for the left side to be contained in the right side. It's important for performance to use d, not d.keys(), as the right side, since checking for containment in a dictionary is much faster than checking in a list (as .keys would be in Python 2, which I guess is what you're using, even though you don't tell us!, based on the syntax for that print:-).