I have a string which I want to convert to a nested dictionary in Python.
Example Input :
import copy
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff.split("/")
final_temp_dict = dict()
for elem in reversed(diff_arr):
if len(final_temp_dict) == 0:
final_temp_dict.setdefault(elem, value)
else:
temp_final_dict = copy.deepcopy(final_temp_dict)
final_temp_dict.setdefault(elem, temp_final_dict)
print (final_temp_dict)
While running this I face an error and I'm not getting the expected output.
The output needed is as a nested dictionary:
{"pathConstraint" : {"latency" : {"latencyValue" : "low"}}}
You could use the following recursive function:
def string_to_dict(keys, value):
key = keys.split('/')
if len(key) == 2:
return {key[1]: value}
else:
return string_to_dict('/'.join(key[:-1]), {key[-1]: value})
Output:
>>> string_to_dict(diff_str, value)
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Note that this assumes that diff_str begins with a / character.
The following is an iterative approach. Note diff_arr[1:] is used to exclude the empty string that is generated from splitting on the initial /.
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff_str.split("/")
for key in list(reversed(diff_arr[1:])):
value = {key: value}
print(value)
Output
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Shorter recursive approach:
def to_dict(d, v):
return v if not d else {d[0]:to_dict(d[1:], v)}
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
print(to_dict(list(filter(None, diff_str.split('/'))), value))
Output:
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
I tried to modify your function as little as possible, this should work just fine
import copy
def func():
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff_str.split("/")
final_temp_dict = dict()
for elem in reversed(diff_arr):
if elem == "":
continue
if len(final_temp_dict) == 0:
final_temp_dict[elem] = value
else:
temp_final_dict = copy.deepcopy(final_temp_dict)
final_temp_dict = {}
final_temp_dict[elem] = temp_final_dict
print (final_temp_dict)
However, there are much nicer ways to do something like this. See the other answers for inspiration.
def convert(items, value):
if not items:
return value
return {items.pop(0): convert(items, value)}
print(convert(diff_str.strip('/').split('/'), 'low'))
for example, let's say i have a dict like this:
bulk_details={
"ad":'ad',
'ad':[
{'ad':'ad'},
{'ad':'ad'}
]
}
I want to encrypt the values in the dict. i'm stuck at parsing the inner dicts inside the list
my code is this:
new_data = {key: {key_: encrypt(val_) for key_, val_ in (val.items() if type(val) is dict else val)} for key, val in (bulk_details.items() if type(bulk_details) is dict else bulk_details) }
This is not nearly as compact as your one-liner, but it solves your problem and you can perhaps make it more compact:
bulk_details = {
'ad':'ad',
'ad2':
[
{'ad':'ad'},
{'ad':'ad'}
]
}
def encrypt(to_encrypt):
return '?' + to_encrypt + '?'
def encrypt_nested(dt):
if isinstance(dt, dict):
for key, value in dt.items():
if isinstance(value, str):
dt[key] = encrypt(value)
else:
encrypt_nested(value)
return dt
else: # elif isinstance(dt, list)
for value in dt:
if isinstance(value, str):
value = encrypt(value)
else:
encrypt_nested(value)
return dt
print(encrypt_nested(bulk_details))
# {'ad': '?ad?', 'ad2': [{'ad': '?ad?'}, {'ad': '?ad?'}]}
It iterates through a nested dict including arrays for any amount of levels using a recursing function.
I'm a beginner programmer and I've been trying to parse a json output file from an API GET request in order to pull longitude and latitude coordinates.
The JSON file looks like this.
The JSON input file is here.
My code for parsing the json file currently looks like this:
ourResult = js['transactions'][0]['meta']
for majorkey, subdict in ourResult.iteritems():
print majorkey
for subkey, value in subdict.iteritems():
print subkey, value
This however, is only returning the one set of values within the 'location' key, and I'm trying to go a level further to pull the 'lon' and 'lat' values.
Any idea what code I should be using for this?
As I understand your question you needed something like:
js = json.loads(response.content)
ourResult = js['transactions'][0]['meta']
for majorkey, subdict in ourResult.iteritems():
print majorkey
if type(subdict) == dict:
for subkey, value in subdict.iteritems():
print subkey, value
You can print dict of arbitrary depth using code
def print_dict_rec( indict ):
for majorkey, subdict in indict.iteritems():
if type(subdict) == dict:
print majorkey
print_dict_rec(subdict)
else:
print majorkey, subdict
print_dict_rec(ourResult)
Code for extracting all values for keys 'lat' and 'lon':
def get_values_json( js, res ):
if type(js) == list:
for e in js:
get_values_json(e, res)
elif type(js) == dict:
for k,v in js.iteritems():
if type(v) == dict or type(v) == list:
get_values_json(v, res)
else:
if k == 'lat' or k == 'lon':
res[k].append(v)
res = {'lat':[], 'lon':[]}
get_values_json(js, res)
print res
If I have a nested dict d = {'a':{'b':{}}} and a string 'a.b.c' and a value 'X'
I need to put the value in the dict based on the key string.
What I want to achieve can be hard coded as d['a']['b']['c'] = 'X' but I need to do it dynamically. The keystring could be of any length.
For bonus points: I also need to create keys if they don't exist like 'a.b.z' but I'm sure I can figure that out if I can work out the case where they already exist.
def set(d, key, value):
dd = d
keys = key.split('.')
latest = keys.pop()
for k in keys:
dd = dd.setdefault(k, {})
dd.setdefault(latest, value)
d = {}
set(d, 'a.b.c', 'X')
set(d, 'a.b.d', 'Y')
print(d)
Result:
{'a': {'b': {'c': 'X', 'd': 'Y'}}}
def recursedict(d,keylist,value=None):
key = keylist.pop(0) # removes and returns the first key
if len(keylist): # True if there are more levels to go down
try: assert type(d[key]) is dict
except KeyError: d[key] = dict()
except AssertionError: raise ValueError("d[{}] is a {}".format(key,type(d[key])))
# if d[key] doesn't exist, make it a dict()
# if d[key] DOES exist, and isn't a dict, raise a KeyError
recursedict(d[key],keylist,value)
# recurse
else:
if value is None:
return d[key]
else:
d[keylist[0]] = value
return value
def setdeepdict(d,attributestr,value): # double entendre intentional
keys = attributestr.split('.')
recursedict(d,keys,value)
def getdeepdict(d,attributestr): # double entendre SUPER intentional
keys = attributestr.split('.')
recursedict(d,keys)
I want to implement a HashMap in Python. I want to ask a user for an input. depending on his input I am retrieving some information from the HashMap. If the user enters a key of the HashMap, I would like to retrieve the corresponding value.
How do I implement this functionality in Python?
HashMap<String,String> streetno=new HashMap<String,String>();
streetno.put("1", "Sachin Tendulkar");
streetno.put("2", "Dravid");
streetno.put("3","Sehwag");
streetno.put("4","Laxman");
streetno.put("5","Kohli")
Python dictionary is a built-in type that supports key-value pairs. It's the nearest builtin data structure relative to Java's HashMap.
You can declare a dict with key-value pairs set to values:
streetno = {
"1": "Sachin Tendulkar",
"2": "Dravid",
"3": "Sehwag",
"4": "Laxman",
"5": "Kohli"
}
You can also set a key-value mapping after creation:
streetno = {}
streetno["1"] = "Sachin Tendulkar"
print(streetno["1"]) # => "Sachin Tendulkar"
Another way to create a dictionary is with the dict() builtin function, but this only works when your keys are valid identifiers:
streetno = dict(one="Sachin Tendulkar", two="Dravid")
print(streetno["one"]) # => "Sachin Tendulkar"
All you wanted (at the time the question was originally asked) was a hint. Here's a hint: In Python, you can use dictionaries.
It's built-in for Python. See dictionaries.
Based on your example:
streetno = {"1": "Sachine Tendulkar",
"2": "Dravid",
"3": "Sehwag",
"4": "Laxman",
"5": "Kohli" }
You could then access it like so:
sachine = streetno["1"]
Also worth mentioning: it can use any non-mutable data type as a key. That is, it can use a tuple, boolean, or string as a key.
Hash maps are built-in in Python, they're called dictionaries:
streetno = {} #create a dictionary called streetno
streetno["1"] = "Sachin Tendulkar" #assign value to key "1"
Usage:
"1" in streetno #check if key "1" is in streetno
streetno["1"] #get the value from key "1"
See the documentation for more information, e.g. built-in methods and so on. They're great, and very common in Python programs (unsurprisingly).
streetno = { 1 : "Sachin Tendulkar",
2 : "Dravid",
3 : "Sehwag",
4 : "Laxman",
5 : "Kohli" }
And to retrieve values:
name = streetno.get(3, "default value")
Or
name = streetno[3]
That's using number as keys, put quotes around the numbers to use strings as keys.
Here is the implementation of the Hash Map using python
For the simplicity hash map is of a fixed size 16.
This can be changed easily.
Rehashing is out of scope of this code.
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class HashMap:
def __init__(self):
self.store = [None for _ in range(16)]
def get(self, key):
index = hash(key) & 15
if self.store[index] is None:
return None
n = self.store[index]
while True:
if n.key == key:
return n.value
else:
if n.next:
n = n.next
else:
return None
def put(self, key, value):
nd = Node(key, value)
index = hash(key) & 15
n = self.store[index]
if n is None:
self.store[index] = nd
else:
if n.key == key:
n.value = value
else:
while n.next:
if n.key == key:
n.value = value
return
else:
n = n.next
n.next = nd
hm = HashMap()
hm.put("1", "sachin")
hm.put("2", "sehwag")
hm.put("3", "ganguly")
hm.put("4", "srinath")
hm.put("5", "kumble")
hm.put("6", "dhoni")
hm.put("7", "kohli")
hm.put("8", "pandya")
hm.put("9", "rohit")
hm.put("10", "dhawan")
hm.put("11", "shastri")
hm.put("12", "manjarekar")
hm.put("13", "gupta")
hm.put("14", "agarkar")
hm.put("15", "nehra")
hm.put("16", "gawaskar")
hm.put("17", "vengsarkar")
print(hm.get("1"))
print(hm.get("2"))
print(hm.get("3"))
print(hm.get("4"))
print(hm.get("5"))
print(hm.get("6"))
print(hm.get("7"))
print(hm.get("8"))
print(hm.get("9"))
print(hm.get("10"))
print(hm.get("11"))
print(hm.get("12"))
print(hm.get("13"))
print(hm.get("14"))
print(hm.get("15"))
print(hm.get("16"))
print(hm.get("17"))
Output:
sachin
sehwag
ganguly
srinath
kumble
dhoni
kohli
pandya
rohit
dhawan
shastri
manjarekar
gupta
agarkar
nehra
gawaskar
vengsarkar
class HashMap:
def __init__(self):
self.size = 64
self.map = [None] * self.size
def _get_hash(self, key):
hash = 0
for char in str(key):
hash += ord(char)
return hash % self.size
def add(self, key, value):
key_hash = self._get_hash(key)
key_value = [key, value]
if self.map[key_hash] is None:
self.map[key_hash] = list([key_value])
return True
else:
for pair in self.map[key_hash]:
if pair[0] == key:
pair[1] = value
return True
else:
self.map[key_hash].append(list([key_value]))
return True
def get(self, key):
key_hash = self._get_hash(key)
if self.map[key_hash] is not None:
for pair in self.map[key_hash]:
if pair[0] == key:
return pair[1]
return None
def delete(self, key):
key_hash = self._get_hash(key)
if self.map[key_hash] is None :
return False
for i in range(0, len(self.map[key_hash])):
if self.map[key_hash][i][0] == key:
self.map[key_hash].pop(i)
return True
def print(self):
print('---Phonebook---')
for item in self.map:
if item is not None:
print(str(item))
h = HashMap()
Python Counter is also a good option in this case:
from collections import Counter
counter = Counter(["Sachin Tendulkar", "Sachin Tendulkar", "other things"])
print(counter)
This returns a dict with the count of each element in the list:
Counter({'Sachin Tendulkar': 2, 'other things': 1})
In python you would use a dictionary.
It is a very important type in python and often used.
You can create one easily by
name = {}
Dictionaries have many methods:
# add entries:
>>> name['first'] = 'John'
>>> name['second'] = 'Doe'
>>> name
{'first': 'John', 'second': 'Doe'}
# you can store all objects and datatypes as value in a dictionary
# as key you can use all objects and datatypes that are hashable
>>> name['list'] = ['list', 'inside', 'dict']
>>> name[1] = 1
>>> name
{'first': 'John', 'second': 'Doe', 1: 1, 'list': ['list', 'inside', 'dict']}
You can not influence the order of a dict.
A dictionary in Python is the best way to implement this. We can create the following dictionary using the given <key,value> pairs:
d = {"1": "Sachin Tendulkar", "2": "Dravid", "3": "Sehwag", "4": "Laxman", "5": "Kohli"}
To extract the value of a particular key, we can directly use d[key]:
name = d["1"] # The value of name would be "Sachin Tendulkar" here
That is my solution for LeetCode problem 706:
A hash map class with three methods: get, put and remove
class Item:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class MyHashMap:
def __init__(self, size=100):
self.items = [None] * size
self.size = size
def _get_index(self, key):
return hash(key) & self.size-1
def put(self, key: int, value: int) -> None:
index = self._get_index(key)
item = self.items[index]
if item is None:
self.items[index] = Item(key, value)
else:
if item.key == key:
item.value = value
else:
while True:
if item.key == key:
item.value = value
return
else:
if not item.next:
item.next = Item(key, value)
return
item = item.next
def get(self, key: int) -> int:
index = self._get_index(key)
if self.items[index] is None:
return -1
item = self.items[index]
while True:
if item.key == key:
return item.value
else:
if item.next:
item = item.next
else:
return -1
def remove(self, key: int) -> None:
value = self.get(key)
if value > -1:
index = self._get_index(key)
item = self.items[index]
if item.key == key:
self.items[index] = item.next if item.next else None
return
while True:
if item.next and item.next.key == key:
item.next = item.next.next
return
else:
if item.next:
item = item.next
else:
return