Reputation: 23
I am trying to make some code where the user inputs a sentence, the sentence is turned into a dict and then the dict is used to get the original sentence back.
Code:
import json
def code():
sentence = input("Please write a sentence: ")
dictionary = {v: k for k,v in enumerate(sentence.split(), start=1)}
with open('Dict.txt', 'w') as fp:
json.dump(dictionary, fp)
print(dictionary)
puncList = ["{","}",",",":","'","[","]","1","2","3","4","5"]
for i in puncList:
for sentence in dictionary:
dictionary=[sentence.replace(i," ") for sentence in dictionary]
print(' '.join(dictionary))
code()
Input:
Hello my name is Bob
Actual output:
{'Hello' : '1', 'name' : '3', 'Bob' : '5', 'my' : '2', 'is' : '4'}
Hello name Bob my is
Desired output:
{'Hello' : '1', 'name' : '3', 'Bob' : '5', 'my' : '2', 'is' : '4'}
Hello my name is Bob
This would be fine too:
{'Hello' : '1', 'my' : '2', 'name' : '3', 'is' : '4', 'Bob' : '5'}
Hello my name is Bob
For the part where I recreate the original sentence, it cant just print the sentence, it has to be from the dict.
Upvotes: 2
Views: 1955
Reputation: 41872
You logic is flawed in that it can't handle sentences with repeated words:
Hello Bob my name is Bob too
{'name': 4, 'Hello': 1, 'Bob': 6, 'is': 5, 'too': 7, 'my': 3}
name Hello Bob is too my
We can deal with that using a defaultdict, making the values arrays of word positions instead of individual numbers. We can further improve things by dealing with your punch list up front via a split. Finally, we can reconstruct the original sentence using a pair of nested loops. We don't want/need an OrderedDict, or sorting, to do this:
import re
import json
from collections import defaultdict
PUNCH_LIST = r"[ {},:'[\]1-5]+"
def code():
dictionary = defaultdict(list)
sentence = input("Please write a sentence: ")
for position, word in enumerate(re.split(PUNCH_LIST, sentence), start=1):
dictionary[word].append(position)
with open('Dict.txt', 'w') as fp:
json.dump(dictionary, fp)
print(dictionary)
position = 1
sentence = []
while position:
for word, positions in dictionary.items():
if position in positions:
sentence.append(word)
position += 1
break
else:
position = 0
print(' '.join(sentence))
code()
EXAMPLE:
Please write a sentence: Hello Bob, my name is Bob too
defaultdict(<class 'list'>, {'is': [5], 'too': [7], 'Bob': [2, 6], 'Hello': [1], 'name': [4], 'my': [3]})
Hello Bob my name is Bob too
Where Dict.txt contains:
{"is": [5], "too": [7], "Bob": [2, 6], "Hello": [1], "name": [4], "my": [3]}
Note that the defaultdict is a convenience, not a requirement. A plain dictionary will do, but you'll have to initialize the lists for each key.
Upvotes: 1
Reputation: 50190
You need to either use OrderedDict
to retain the element order, or sort the dictionary elements before you print them out. You've already got an OrderedDict
answer, so here's how to use the dict you created:
print(' '.join(k for (k, v) in sort(dictionary.items(), key=lambda x: x[1])))
Incidentally, your approach has a bug: If you apply it to a sentence with repeated words, e.g., "boys will be boys", you'll find that there's no element with index 1
in your dictionary since (boys, 4)
will overwrite (boys, 1)
.
Upvotes: 2
Reputation: 78556
Use an OrderedDict
on enumerate
, like so:
from collections import OrderedDict
s = "Hello my name is Bob"
d = OrderedDict((v, i) for i, v in enumerate(s.split(), 1))
print(d)
# OrderedDict([('Hello', 1), ('my', 2), ('name', 3), ('is', 4), ('Bob', 5)])
s_rebuild = ' '.join(d)
print(s_rebuild)
# 'Hello my name is Bob'
Since the dictionary is already ordered, the values are not used for rebuilding the string.
Upvotes: 1