I have a string as given below
dit ='{p_d: {a:3, what:3.6864e-05, s:lion, sst:{c:-20, b:6, p:panther}}}'
And I have a list of elements which I wanted to search in the above string and replace them with double quotes.
['', 'p_d', '', '', 'a', '3', '', 'what', '3.6864e-05', '', 's', 'lion', '', 'sst', '', 'c', '-20', '', 'b', '6', '', 'p', 'panther', '', '', '']
If I do search and replace using simple .replace it doesn't work as expected and can understand
import yaml
import ast
import json
import re
rep = {":": " ", "'":" ", "{":" ", "}":" ", ",": " "}
quot = "\""
dit = '{p_d: {a:3, what:3.6864e-05, s:lion, sst:{c:-20, b:6, p:panther}}}'
def replace_all(text, dic):
for i, j in dic.items():
text = text.replace(i, j)
print("replace_all: text {}".format(text))
return text
element_list_temp = replace_all(dit, rep)
element_list = element_list_temp.split(" ")
for z in element_list:
if z != "" and z in dit:
dit = dit.replace(z, quot+z+quot)
print(dit)
Output:
{""p"_d": {"a":"3", wh"a"t:"3"."6"8"6"4e-05, "s":"lion", "s""s"t:{"c":"-20", "b":"6", "p":"p""a"nther}}}
Desired Output:
'{"p_d": {"a":"3", "what":"3.6864e-05", "s":"lion", "sst":{"c":"-20", "b":"6", "p":"panther"}}}'
How to exactly match the string in the list one by one and replace them with double quotes.
Updates:
Different input
import yaml
import ast
import json
import re
rep = {":": " ", "'":" ", "{":" ", "}":" ", ",": " "}
quot = "\""
# dit = '{p_d: {a:3, what:3.6864e-05, s:lion, sst:{c:-20, b:6, p:panther}}}'
dit = "'{p_d: '{a:3, what:3.6864e-05, s:lion, vec_mode:'{2.5, -2.9, 3.4, 5.6, -8.9, -5.67, 2, 2, 2, 2, 5.4, 2, 2, 6.545, 2, 2}, sst:'{c:-20, b:6, p:panther}}}"
seps = ":'{}, "
val_strings = re.findall(f"[^{seps}]+", dit)
print("val_strings: {}".format(val_strings))
sep_strings = re.findall(f"[{seps}]+", dit)
print("sep_strings: {}".format(sep_strings))
seq = [f'{b}"{v}"' for b, v in zip(sep_strings, val_strings)] + sep_strings[-1:]
print("sep: {}".format(seq))
dit = "".join(seq)
print(dit)
Dict = json.loads(dit)
print(Dict)
result = yaml.dump(Dict)
print(result)
print(result.replace("'",""))
Output from above code
Think its failing because of the key:value pair of the dictionary. Checking at my end as well if there is a way to print them as arrays.
val_strings: ['p_d', 'a', '3', 'what', '3.6864e-05', 's', 'lion', 'vec_mode', '2.5', '-2.9', '3.4', '5.6', '-8.9', '-5.67', '2', '2', '2', '2', '5.4', '2', '2', '6.545', '2', '2', 'sst', 'c', '-20', 'b', '6', 'p', 'panther']
sep_strings: ["'{", ": '{", ':', ', ', ':', ', ', ':', ', ', ":'{", ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', '}, ', ":'{", ':', ', ', ':', ', ', ':', '}}}']
sep: ['\'{"p_d"', ': \'{"a"', ':"3"', ', "what"', ':"3.6864e-05"', ', "s"', ':"lion"', ', "vec_mode"', ':\'{"2.5"', ', "-2.9"', ', "3.4"', ', "5.6"', ', "-8.9"', ', "-5.67"', ', "2"', ', "2"', ', "2"', ', "2"', ', "5.4"', ', "2"', ', "2"', ', "6.545"', ', "2"', ', "2"', '}, "sst"', ':\'{"c"', ':"-20"', ', "b"', ':"6"', ', "p"', ':"panther"', '}}}']
'{"p_d": '{"a":"3", "what":"3.6864e-05", "s":"lion", "vec_mode":'{"2.5", "-2.9", "3.4", "5.6", "-8.9", "-5.67", "2", "2", "2", "2", "5.4", "2", "2", "6.545", "2", "2"}, "sst":'{"c":"-20", "b":"6", "p":"panther"}}}
Traceback (most recent call last):
File "./ditoyaml_new.py", line 36, in <module>
Dict = json.loads(dit)
File "/usr/lib64/python3.6/json/__init__.py", line 354, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Expected Output with the json.load and dump as dictionary and if the key: value dictionary pair isnt available and put something like list or array. Checking at my end as well.
p_d:
a: 3
s: lion
sst:
b: 6
c: -20
p: panther
vec_mode:
[-8.9,
-5.67,
-2.9,
2,
2.5,
3.4,
5.4,
5.6,
6.545]
what: 3.6864e-05
Here is one way using regular expressions
import re
dit = '{p_d: {a:3, what:3.6864e-05, s:lion, sst:{c:-20, b:6, p:panther}}}'
seps = ":'{}, "
val_strings = re.findall(fr"[^{seps}]+", dit)
sep_strings = re.findall(fr"[{seps}]+", dit)
seq = [f'{b}"{v}"' for b, v in zip(sep_strings, val_strings)] + sep_strings[-1:]
dit = "".join(seq)
print(dit)
Output:
{"p_d": {"a":"3", "what":"3.6864e-05", "s":"lion", "sst":{"c":"-20", "b":"6", "p":"panther"}}}
JSON test:
import json
print(json.loads(dit))
Output:
{'p_d': {'a': '3', 'what': '3.6864e-05', 's': 'lion', 'sst': {'c': '-20', 'b': '6', 'p': 'panther'}}}
puzzle = [[' 1', ' 2', ' 3', ' 4'], [' 5', ' 6', ' 7', ' 8'],[ ' 9', '10', '11', '12'], ['13', '14', '15', ' X']]
def find_pos(alist, item):
for i in alist:
for j in range(4):
if i[j] == item:
row = alist.index(i)
col = j
find_pos(puzzle,' X')
a = row
print(a)
I think I defined the name row by running the function find_pos, if not, how to fix it to get row
Do not put any print in the find_pos function
Just return the values from the function:
puzzle = [[' 1', ' 2', ' 3', ' 4'], [' 5', ' 6', ' 7', ' 8'],[ ' 9', '10', '11', '12'], ['13', '14', '15', ' X']]
def find_pos(alist, item):
for i in alist:
for j in range(4):
if i[j] == item:
row = alist.index(i)
col = j
return row, col
row, col = find_pos(puzzle,' X')
print(row)
Note that if the item isn't found, it will return None (because every function that doesn't return anything returns None by default), in which case the code will throw an error.
I am experiencing a strange faulty behaviour, where a dictionary is only appended once and I can not add more key value pairs to it.
My code reads in a multi-line string and extracts substrings via split(), to be added to a dictionary. I make use of conditional statements. Strangely only the key:value pairs under the first conditional statement are added.
Therefore I can not complete the dictionary.
How can I solve this issue?
Minimal code:
#I hope the '\n' is sufficient or use '\r\n'
example = "Name: Bugs Bunny\nDOB: 01/04/1900\nAddress: 111 Jokes Drive, Hollywood Hills, CA 11111, United States"
def format(data):
dic = {}
for line in data.splitlines():
#print('Line:', line)
if ':' in line:
info = line.split(': ', 1)[1].rstrip() #does not work with files
#print('Info: ', info)
if ' Name:' in info: #middle name problems! /maiden name
dic['F_NAME'] = info.split(' ', 1)[0].rstrip()
dic['L_NAME'] = info.split(' ', 1)[1].rstrip()
elif 'DOB' in info: #overhang
dic['DD'] = info.split('/', 2)[0].rstrip()
dic['MM'] = info.split('/', 2)[1].rstrip()
dic['YY'] = info.split('/', 2)[2].rstrip()
elif 'Address' in info:
dic['STREET'] = info.split(', ', 2)[0].rstrip()
dic['CITY'] = info.split(', ', 2)[1].rstrip()
dic['ZIP'] = info.split(', ', 2)[2].rstrip()
return dic
if __name__ == '__main__':
x = format(example)
for v, k in x.iteritems():
print v, k
Your code doesn't work, at all. You split off the name before the colon and discard it, looking only at the value after the colon, stored in info. That value never contains the names you are looking for; Name, DOB and Address all are part of the line before the :.
Python lets you assign to multiple names at once; make use of this when splitting:
def format(data):
dic = {}
for line in data.splitlines():
if ':' not in line:
continue
name, _, value = line.partition(':')
name = name.strip()
if name == 'Name':
dic['F_NAME'], dic['L_NAME'] = value.split(None, 1) # strips whitespace for us
elif name == 'DOB':
dic['DD'], dic['MM'], dic['YY'] = (v.strip() for v in value.split('/', 2))
elif name == 'Address':
dic['STREET'], dic['CITY'], dic['ZIP'] = (v.strip() for v in value.split(', ', 2))
return dic
I used str.partition() here rather than limit str.split() to just one split; it is slightly faster that way.
For your sample input this produces:
>>> format(example)
{'CITY': 'Hollywood Hills', 'ZIP': 'CA 11111, United States', 'L_NAME': 'Bunny', 'F_NAME': 'Bugs', 'YY': '1900', 'MM': '04', 'STREET': '111 Jokes Drive', 'DD': '01'}
>>> from pprint import pprint
>>> pprint(format(example))
{'CITY': 'Hollywood Hills',
'DD': '01',
'F_NAME': 'Bugs',
'L_NAME': 'Bunny',
'MM': '04',
'STREET': '111 Jokes Drive',
'YY': '1900',
'ZIP': 'CA 11111, United States'}
I have following dict:
defaultdict(<type 'dict'>,
{'11': {('extreme_fajita', 'jalapeno_poppers'): '4',('test12', 'test14'): '5'},
'10': {('jalapeno_poppers', 'test', ): '2', ('test2',): '3', ('test14',): '5'}
}
And I want to search on based on inner key i.e ('test2',) I should get the value from inner dictionary and parent key (outer key)
i.e searching for ('test2',) I should get get ['10', '3'] or whole like ['10', '('test2', )', '3']
I'm going to assume your defaultdict looks like:
defaultdict = {'11': {('extreme_fajita', 'jalapeno_poppers'): '4',('test12', 'test14'): '5'}, '10': {('jalapeno_poppers', 'test2', ): '2', ('test2',): '3', ('test14',): '5'} }
If that's the case, then you can use:
searchValue = 'test2'; found = []
for masterkey,mastervalue in defaultdict.iteritems():
for childkey,childvalue in mastervalue.iteritems():
if searchValue in childkey:
found.append(childvalue)
print found
Dictionary is not ordered so you will not get in the order as '2','3' instead you can get all values from the dictionary where 'test2' found. I have following code for this:
def getKeys(d1, path="", lastDict=list()):
for k in d1.keys():
if type(k) is tuple:
if 'test2' in k:
print "test2 found at::", path + "->" , k
print "Value of test2::", d1[k]
print "Values in parent::", [kl for kl in lastDict[len(lastDict)-1].values()]
elif type(d1[k]) is dict:
lastDict.append(d1[k])
if path == "":
path = k
else:
path = path + "->" + k
getKeys(d1[k], path)
d = {'11': {('extreme_fajita', 'jalapeno_poppers'): '4',('test12', 'test14'): '5'}, '10': {('jalapeno_poppers', 'test', ): '2', ('test2',): '3', ('test14',): '5'}}
getKeys(d)
Output:
test2 found at:: 11->10-> ('test2',)
Value of test2:: 3
Values in parent:: ['2', '5', '3']