Recursively create a nested dictionary from string [duplicate] - python

This question already has answers here:
Converting list to nested dictionary
(4 answers)
Closed 5 years ago.
I have an issue that I've been trying to sort out. I have a string that needs to be converted to an nested dictionary with the keys and values based off the adjacent words in the string. Here is an example:
graphMaster = {}
inputSentence = "I have a dog named Max."
I would like to take this string, and convert it into a dictionary resembling the output below:
print graphMaster
{'I': {'have': {'a': {'dog': {'named': 'Max'}}}}}
I have tried the following:
graphMaster = {}
inputSentence = "I have a dog named Max."
while True:
inputList = inputSentence.strip().split(' ')
for currentIndex, word in enumerate(inputList):
nextIndex = currentIndex + 1
if nextIndex < len(inputList):
if word not in graphMaster.keys():
graphMaster[word] = inputList[nextIndex]
elif word in graphMaster.keys():
break
print graphMaster
I couldn't find a duplicate problem here and I pre-apologize if one exists that I couldn't find. Any help is greatly appreciated.

You could do something like this:
outdict = {}
curdict = outdict
for f in inputSentence.split(' '):
curdict[f] = {}
curdict = curdict[f]
print outdict
Where curdict is only pointing to a location in the output dictionary.

Related

Best method to match words between a list and a dictionary, returning only the ones that are unique for a key without the use of modules

I'm writing this script where archive contains the words that a person has said and their age, and clues are sentences where some words are extracted to match with the most likely person that said them. Words that work as a clue are marked with a * and all clues should be uniquely used by a person.
from typing import List, Dict, TextIO, Tuple
def who_did_it(archive: Dict[str, List[tuple]], clues: str) -> str:
word_list = []
#contains person and a list of its words in a list
clean_clue = get_words(clues)
#get_words: extract the clues clean into a list without the `*`
suspect = []
#a list for the most likely person that did it
dict_list = {}
#person as key, a list of words as values
for people in archive:
clues = archive.get(people)
word_list.append([people, get_words(clues[0])])
clean_clue.sort()
for person, words in word_list:
dict_list.setdefault(person, words)
numb = 0
for names in dict_list:
for clues in clean_clue:
if clues in dict_list.get(names):
numb = numb + 1
elif tags not in dict_list.get(names):
numb = numb - 1
if numb == 1:
suspect.append(names)
counter = 0
if len(suspect) == 1:
print(suspect[0])
else:
print('need more evidence')
The problem comes when I use my test cases, some of them doesn't seem to work because of the way I'm doing it, is there any other way to compare this values? How can I compare this values in an efficient way without using modules?
You are better off using a dict with keys that are your clues/weapons and sets of names as values:
def who(things,clues):
""" Returns a sorted list of (name, [clues,...]) tuples, sorted by longest len first"""
result = {}
for t in things:
for name in clues[t]:
result.setdefault(name,[])
result[name].append(t)
return sorted(result.items(), key=lambda x:-len(x[1]))
clues = { "knife":{"Joe","Phil"}, "club":{"Jane","John"}, "ice":{"Joe","Neffe"}}
print(who({"knife","ice"}, clues))
Output:
[('Joe', ['knife', 'ice']), ('Phil', ['knife']), ('Neffe', ['ice'])]
The reason the other way round is better: you are looking for the clues - which should be the keys.
Your logic is mixed up with the parsing which is not a very good thing. If you separate them things are much easier to understand.
from typing import List, Dict
def get_words(sentence: str) -> List:
return [word[1:] for word in sentence.split() if word.startswith('*')]
def who_did_it(archive: Dict[str, List[str]], clues: List[str]) -> str:
suspect = []
#a list for the most likely person that did it
for name, belongings in archive.items():
if all(clue in belongings for clue in clues):
suspect.append(name)
if len(suspect) == 1:
print(suspect[0])
else:
print('need more evidence')
facts = {
'martin': ('I had a knife and a *broom', 22),
'jose': ('I had a *knife', 21),
}
archive = { name : get_words(fact[0]) for name, fact in facts.items()}
who_did_it(archive, get_words('he had a *knife'))

Dynamically create variables from split string

What I would like to do is to separate each word of a string and dynamically create variables that I can use independently afterwards, like:
String = 'Jurassic Park 3'
Variable1= 'jurassic'
Variable2= 'park'
Variable3= '3'
The thing is, the string can be very long. So it has to be able to handle a sentence containing many words.
I already have the beginning of a code:
import re
input = str(d["input_text"])
l = []
regex = re.compile(r'(\d+|\s+)')
s = regex.split(input)
l = []
for elem in s:
if elem =='':
continue
else:
l.append(elem)
ret_dict = {}
ret_dict["text_list"] = l
ret_dict["returncode"] = 0 # set to 1 to output on the FAILURE output
return ret_dict
with that code, at the moment i have this
input variable = input_text
output variable = text_list
I would like
input variable = input_text
output variable1 = variable1
output variable2 = variable2
output variable3 = variable3
output variable4 = variable4
etc
When having to define an unknown amount of variables, I like to use Dictionaries. It could be done like this:
string = 'Jurassic Park 3' # Original string
string_list = string.split() # Returns: ['Jurassic', 'Park', '3']
dic = {}
for i in range(len(string_list)):
var_name = 'Variable{}'.format(i+1) # Define name of variable, start with 'Variable1'
dic[var_name] = string_list[i] # Insert variable name as key and list entry as value
Printing the dictionary will return:
{'Variable1': 'Jurassic', 'Variable2': 'Park', 'Variable3': '3'}
To access e.g. Variable2, you could do:
dic['Variable2']
which returns
'Park'
If the number of variables become large, I think having them collected in a Dictionary could be easier to handle rather than having the variables defined individually like your question suggests.
If you had e.g. 100 variables but were unsure of the count, it would be easy to check the size of the Dictionary. It would probably be a little harder to keep track of all those variables when they are scattered around and not collected in a bunch.
First you can split your string in a list like this
string = "Jurassic Park 3"
string_list = string.split()
printing this will output:
['Jurassic', 'Park', '3']
Then we itterate through the list like this
for i in range(0, len(string_list)):
exec("word%d = %s" % (i + 1, repr(string_list[i])));
What this does is go through the list of words and puts everything in the variable word1 word2 word3 and however long your string goes on.
Hope this helps
I found something else, and it does work. I just need to do one more thing on it. if element of the list is 'space', add it to the begginning of the next element.
import re
input = str(d["Jurassic Park 3"])
l = []
regex = re.compile(r'(\d+|\s+)')
s = regex.split(input)
l = []
for elem in s:
if elem =='':
continue
else:
l.append(elem)
ret_dict = {}
ret_dict["text_list"] = l
ret_dict["returncode"] = 0 # set to 1 to output on the FAILURE output
return ret_dict
This does return me :
["Jurassic"," ","Park"," ","3"]
and i would like to have:
["Jurassic"," Park"," 3"]

Call multiple dictionaries who names involve i in a loop? [duplicate]

This question already has answers here:
How can I select a variable by (string) name?
(5 answers)
Closed 8 months ago.
I would like to call multiple dictionaries using a for loop. I am unsure how to call multiple dictionaries properly, and I can't figure out if its possible using concatenation. The code below should explain my thinking even though the print statement is incorrect.
stat0 = {}
stat0["bob"] = 0
stat1 = {}
stat1["bob"] = 0
stat2 = {}
stat2["bob"] = 0
for i in range(3):
print(stat(i))
How about putting them in a collection, and then getting value generically:
for hm in [stat0, stat1, stat2]
print(hm["bob"])
Instead of naming your dictionaries, just put them into another dictionary:
#UNTESTED
stat = { 0: stat0, 1: stat1, 2: stat2 }
for i in range(3):
print(stat[i])
Or, use an iterative style more appropriate for dict:
#UNTESTED
for i, d in stat.items():
print(i, d)

Creating a Python dictionary

Is it possible to create a dictionary like this?
data = {(136-00000-0001 : 072-00000-0001,072-00000-0002,072-00000-0003),
(136-00000-0002 : 072-00000-0002,072-00000-0003,072-00000-0004)}
text = input("Put your 072-XXXXX-XXXX number in here: ")
wrapper =[]
for number in text:
if number in data.keys()
wrapper.append(data[number]
for w in wrapper:
print(w, end=" ")
I have a wrapper called 136-xxxxx-xxxx where 3*072-xxxxx-xxxx are in it.
All I want to do is, asking for a 072-xxxxx-xxxx number and the program is giving me
the Wrapper number of it back.
For example:
asking for 072-00000-0004
answer -> it´s inside 136-00000-0002
The only way I know is, for example that morse thing, where
morse = {"a":".-", "b":"-...", but is there a way like this for my example at the top?
You would need to store multiple values for your keys in a list,tuple etc.. You cannot have more than one value for a key.
data = {"136-00000-0001" : ["072-00000-0001","072-00000-0002","072-00000-0003"],"136-00000-0002" : ["072-00000-0002","072-00000-0003","072-00000-0004"]}
print ( data.values())
[['072-00000-0001', '072-00000-0002', '072-00000-0003'], ['072-00000-0002', '072-00000-0003', '072-00000-0004']]
To append to a keys values:
data["136-00000-0001"].append("whatever")
Check if value is in the dict and print the key,value pair.:
In [5]: for k,v in data.items():
if "072-00000-0004" in v:
print (k,v)
...:
136-00000-0002 ['072-00000-0002', '072-00000-0003', '072-00000-0004']
Use strings if you want use the format 072-00000-0002 will give an error SyntaxError: invalid token
.
In Python 2.x:
>>> data = {"136-00000-0001":["072-00000-0001","072-00000-0002","072-00000-0003"],"136-00000-0002":["072-00000-0002","072-00000-0003","072-00000-0004"]}
>>> text = raw_input("Put your 072-XXXXX-XXXX number in here: ")
Put your 072-XXXXX-XXXX number in here: 072-00000-0004
>>> for d in data:
... if text in data[d]:
... print d
136-00000-0002
And for Python 3 you have to use input() instead of raw_input() and print() as a function.
>>> data = {"136-00000-0001":["072-00000-0001","072-00000-0002","072-00000-0003"],"136-00000-0002":["072-00000-0002","072-00000-0003","072-00000-0004"]}
>>> text = input("Put your 072-XXXXX-XXXX number in here: ")
Put your 072-XXXXX-XXXX number in here: 072-00000-0004
>>> for d in data:
... if text in data[d]:
... print(d)
136-00000-0002

Python dictionary get method in assignment [duplicate]

This question already has an answer here:
Dictionary syntax error "can't assign to function call"
(1 answer)
Closed 9 months ago.
All,
I'm looping over a dictionary and counting the values that occur. To do this, I'm using the get method in the assignment statement for another dictionary. This returns a syntax error "can't assign to function call"
counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key,value in mydict.iteritems():
counts(value[1]) = counts.get(value[1], 0) + 1
Why would the assignment try to point to the function, rather than the return value?
counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key,value in mydict.iteritems():
counts[value[1]] = counts.get(value[1], 0) + 1
You need brackets, not parenthesis, to get an item from a dictionary.
Also, You're doing this the hard way.
from collections import defaultdict
# automatically start each count at zero
counts = defaultdict(int)
# we only need the values, not the keys
for value in mydict.itervalues():
# add one to the count for this item
counts[value[1]] += 1
or
# only on Python 2.7 or newer
from collections import Counter
counts = Counter(value[1] for value in mydict.itervalues())
Instead of counts(value[1]) = ... you want counts[value[1]] = ....
Change this:
counts(value[1])
to this:
counts[value[1]]
Code looks like this:
counts = {}
mydict = {'a':[1,2,5], 'b': [1,2,10]}
for key, value in mydict.iteritems():
counts[value[1]] = counts.get(value[1], 0) + 1
counts[value[1]] = counts.get(value[1], 0) + 1
should be
counts[value[1]] = counts.get(value[1], 0) + 1

Categories