Dictionary thesaurus replacing substrings - string

So I have a dictionary that contains words and their synonyms. The purpose is to replace substrings in a string with a random synonym. Here's my code.
import random
thesaurus = {
"happy":["glad", "blissful", "ecstatic", "at ease"],
"sad" :["bleak", "blue", "depressed"]
}
phrase = input("Enter a phrase: ")
for x in phrase.split():
if x in thesaurus:
ran = len(thesaurus[x])
print( len(thesaurus[x]))
ranlis = random.randint(0,ran - 1)
phrase = phrase.replace(x,str.upper(thesaurus[x][ranlis]))
print(phrase)
If I input "happy happy happy"
The output is:
ECSTATIC ECSTATIC ECSTATIC
I want it to print a different synonym each time(or at least be able to. I understand that it is random).
So:
ECSTATIC BLISSFUL AT EASE
I understand the error in my logic but am unsure how to fix it.

The key is to replace only one occurrence. The replace() function takes 3 parameters, the third being the number of occurrences you want to replace.
So:
phrase = phrase.replace(x,str.upper(thesaurus[x][ranlis]),1)

Related

How to substitute a repeating character with the same number of a different character in regex python?

Assume there's a string
"An example striiiiiing with other words"
I need to replace the 'i's with '*'s like 'str******ng'. The number of '*' must be same as 'i'. This replacement should happen only if there are consecutive 'i' greater than or equal to 3. If the number of 'i' is less than 3 then there is a different rule for that. I can hard code it:
import re
text = "An example striiiiing with other words"
out_put = re.sub(re.compile(r'i{3}', re.I), r'*'*3, text)
print(out_put)
# An example str***iing with other words
But number of i could be any number greater than 3. How can we do that using regex?
The i{3} pattern only matches iii anywhere in the string. You need i{3,} to match three or more is. However, to make it all work, you need to pass your match into a callable used as a replacement argument to re.sub, where you can get the match text length and multiply correctly.
Also, it is advisable to declare the regex outside of re.sub, or just use a string pattern since patterns are cached.
Here is the code that fixes the issue:
import re
text = "An example striiiiing with other words"
rx = re.compile(r'i{3,}', re.I)
out_put = rx.sub(lambda x: r'*'*len(x.group()), text)
print(out_put)
# => An example str*****ng with other words

Will it help in this problem to convert the string into a list?

I have a question. I am not looking for the answer to this exercise, just a pointer. My question is: will this be easier to solve if the two-word string is converted to a List?
ANIMAL CRACKERS: Write a function takes a two-word string and returns True if both words begin with same letter
animal_crackers('Levelheaded Llama') --> True
animal_crackers('Crazy Kangaroo') --> False
Yes, in this problem it would help to use the .split() method to split the string into a list of the two words.
Generally, the same data can be represented in different ways, and you want to use a representation which aligns with what you need to do with the data. Since this problem is about words, then "a list of words" aligns closer with what you need to do than "a string with two words" does.
Having a list of words allows you to write code that refers to "the first word" (i.e. words[0]) and "the second word" (i.e. words[1]). There is no comparably-simple way to refer to individual words in the original string.
Thanks everyone. I realised quite soon after i posted that the .split() function was what i needed to use. This was my solution.
def animal_crackers(string):
twoWords = (string.split(' '))
if twoWords[0][0].upper() == twoWords[1][0].upper():
return True
Do a split on the string input myListOfTwoSriting = stringInput.split(" "), next split the 2 string link that : firstletter = myListOfTwoSriting [0].split("")[0] then firstletterOfSeconde = myListOfTwoSriting [1].split("")[0] for the seconde.
next:
if firstletter == firstletterOfSeconde :
return True
else:
return False

String Operations Confusion? ELI5

I'm extremely new to python and I have no idea why this code gives me this output. I tried searching around for an answer but couldn't find anything because I'm not sure what to search for.
An explain-like-I'm-5 explanation would be greatly appreciated
astring = "hello world"
print(astring[3:7:2])
This gives me : "l"
Also
astring = "hello world"
print(astring[3:7:3])
gives me : "lw"
I can't wrap my head around why.
This is string slicing in python.
Slicing is similar to regular string indexing, but it can return a just a section of a string.
Using two parameters in a slice, such as [a:b] will return a string of characters, starting at index a up to, but not including, index b.
For example:
"abcdefg"[2:6] would return "cdef"
Using three parameters performs a similar function, but the slice will only return the character after a chosen gap. For example [2:6:2] will return every second character beginning at index 2, up to index 5.
ie "abcdefg"[2:6:2] will return ce, as it only counts every second character.
In your case, astring[3:7:3], the slice begins at index 3 (the second l) and moves forward the specified 3 characters (the third parameter) to w. It then stops at index 7, returning lw.
In fact when using only two parameters, the third defaults to 1, so astring[2:5] is the same as astring[2:5:1].
Python Central has some more detailed explanations of cutting and slicing strings in python.
I have a feeling you are over complicating this slightly.
Since the string astring is set statically you could more easily do the following:
# Sets the characters for the letters in the consistency of the word
letter-one = "h"
letter-two = "e"
letter-three = "l"
letter-four = "l"
letter-six = "o"
letter-7 = " "
letter-8 = "w"
letter-9 = "o"
letter-10 = "r"
letter11 = "l"
lettertwelve = "d"
# Tells the python which of the character letters that you want to have on the print screen
print(letter-three + letter-7 + letter-three)
This way its much more easily readable to human users and it should mitigate your error.

How can I replace each letter in the sentence to sentence without breaking it?

Here's my problem.
sentence = "This car is awsome."
and what I want do do is
sentence.replace("a","<emoji:a>")
sentence.replace("b","<emoji:b>")
sentence.replace("c","<emoji:c>")
and so on...
But of course if I do it in that way the letters in "<emoji:>" will also be replaced as I go along. So how can I do it in other way?
As Carlos Gonzalez suggested:
create a mapping dict and apply it to each character in sequence:
sentence = "This car is awsome."
# mapping
up = {"a":"<emoji:a>",
"b":"<emoji:b>",
"c":"<emoji:c>",}
# apply mapping to create a new text (use up[k] if present else default to k)
text = ''.join( (up.get(k,k) for k in sentence) )
print(text)
Output:
This <emoji:c><emoji:a>r is <emoji:a>wsome.
The advantage of the generator expression inside the ''.join( ... generator ...) is that it takes each single character of sentence and either keeps it or replaces it. It only ever touches each char once, so there is no danger of multiple substitutions and it takes only one pass of sentence to convert the whole thing.
Doku: dict.get(key,default) and Why dict.get(key) instead of dict[key]?
If you used
sentence = sentence.replace("a","o")
sentence = sentence.replace("o","k")
you would first make o from a and then make k from any o (or a before) - and you would have to touch each character twice to make it happen.
Using
up = { "a":"o", "o":"k" }
text = ''.join( (up.get(k,k) for k in sentence) )
avoids this.
If you want to replace more then 1 character at a time, it would be easier to do this with regex. Inspired by Passing a function to re.sub in Python
import re
sentence = "This car is awsome."
up = {"is":"Yippi",
"ws":"WhatNot",}
# modified it to create the groups using the dicts key
text2 = re.sub( "("+'|'.join(up)+")", lambda x: up[x.group()], sentence)
print(text2)
Output:
ThYippi car Yippi aWhatNotome.
Doku: re.sub(pattern, repl, string, count=0, flags=0)
You would have to take extra care with your keys, if you wanted to use "regex" specific characters that have another meaning if used as regex-pattern - f.e. .+*?()[]^$

A converter that converts a string to a different string

Okay it's really complicated to explain, input required, user is typing his input and then it prints what he said but each character is replaced with another character (not random, each symbol will equal a symbol, for example "a" will be "9". Like this) so if I put the input "a" it will return "9", let's say "b" = "5" and "c" = "$". So my if my input is abc (can be ABC it doesn't matter, it will do the .upper), it will print "95$". Like an encoder, each symbol will equal to something and then it will know what to return. I wasn't really sure if it is clear, let me know what isn't clear and I'll make sure to respond as quickly as possible. I tried doing some things but it's a bit hard, I'm still a beginner and that's how I learn. Thanks a lot!
EDIT
A better example:
asking for input,
input: abc,
output: 95$
You can create a dictionary (dict).
my_encoder = dict({"a":"9", "b":"5","c":"$"})
How to use:
value = my_encoder["a"]
print(value) # 9
In your case for a input of abc:
input = "abc"
encoded_input = ""
for character in input:
encoded_input = encoded_input + my_encoder[character]
print(encoded_input) # 95$
Python strs have a built-in translate function. Pass in a dictionary of {<code point>:<replacement>}. In the case of what you've shown, you could do:
print(input().upper().translate({65:'9',66:'5',67:'$'}))
If you have a lot of mappings to do, you can use the str#maketrans static method with two strings of equal length.
trans = str.maketrans('ABC', '95$')
print(input().upper().translate(trans))

Resources