User9123
User9123

Reputation: 23

How to create a sentence from a dictionary

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

Answers (3)

cdlane
cdlane

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

alexis
alexis

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

Moses Koledoye
Moses Koledoye

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

Related Questions