split string update numbers only - python

I have a function using raw_input getting a sentence from user. Then my second function splits the sentence so I am only trying to update the numbers on the sentence. This is the split sentence:
['You', 'are', '42', 'this', 'year']
I am trying to update 42 to 43 do a return and print 'You are 43 this year'
I am able to pull the number by using isdigit() but I can't increase it. This is what I have so far:
def GetDigits(sentence):
for i in sentence:
if i.isindigit():
i = i +1
return sentence

Numbers in Python are immutable objects, so when you do i = i+1, you are creating a new object. This new object is not part of your original sentence object. Also, '42' is a string. You can't apply numeric add operation on it. You need to convert it to an integer first.
This is what you need -
def GetDigits(sentence):
for idx, value in enumerate(sentence):
if value.isdigit():
sentence[idx] = int(value) +1
return sentence

There is a built in method for strings that would be much better for this, format()
age = raw_input('How old are you?')
sentence = 'You are {} this year'
print(sentence.format(age))
If you need to update it you can:
print(sentence.format(int(age) + 1))
Alternatively as function utilizing a generator comprehension:
def get_digits(sentence):
return ' '.join(str(int(word) + 1) if word.isdigit() else word for word in sentence.split())

Another hacky way through regex using re module,
import re
sentence = input("Enter the sentence : \n")
def GetDigits(sentence):
L = []
for i in sentence.split():
if re.match(r'\d+$', i):
i = int(i)+1
L.append(str(i))
else:
L.append(i)
sentence = ' '.join(L)
return(sentence)
print(GetDigits(sentence))
Output:
Enter the sentence :
You are 42 this year
You are 43 this year

You're trying to add 1 to a string, as '42' isn't the same as 42.
You need to change '42' to an int first using int(v), then increase it.
def GetDigits(sentence):
for i, v in enumerate(sentence):
if v.isdigit():
sentence[i] = str(int(v) + 1)
return sentence

The key issue here is that you're trying to find a function that lets you know when it's safe/correct to convert a string to an int—but there is no such function. There are various approximations, but the simplest thing to do is just try to convert the string. This is a general principle in Python, EAFP: Easier to Ask Forgiveness than Permission. The language has been designed around the fact that the way to check whether something will work is to just do it, then handle the case where it didn't work (normally meaning an exception). Trying to fight that design is just going to make your life harder.
But that's not the only issue; there are multiple problems here.
isindigit isn't a method of strings. Maybe you meant isdigit?
isdigit doesn't give you the right answer for, say, -3—or, for that matter, integers in non-Western scripts (which may return true for isdigit but not actually be interpretable as integers by Python).
Just because i is a string representing an integer doesn't mean it's an integer; it's still a string, and i + 1 is still a TypeError. You need to call int(i) to get its value as a number.
Just reassigning to i doesn't affect sentence at all. All you're doing is making the local variable i into a name for a different value. You need to do something with that i—either build a new sentence, or modify the sentence in-place (e.g., by using enumerate to keep track of the index, so you can do sentence[index] = …).
While it isn't clear what you're doing with the results, I'll bet you actually want to get strings back, not a mix of strings and integers, so you'll probably want to convert back to str after adding 1.
So, what you want is something like this:
def GetDigits(sentence):
new_sentence = []
for i in sentence:
try:
i = str(int(i) + 1)
except ValueError:
pass
new_sentence.append(i)
return new_sentence
However, this might be a little too clever as written. If i doesn't represent an integer, int(i) will raise a ValueError, meaning i is still referring to the original string, which we add to new_sentence. Otherwise, we'll convert it to an integer, add 1, convert back to a string, and make i refer to this new string, which we add to new_sentence. If you don't understand why new_sentence.append(i) always does the right thing, you should rewrite it more explicitly.

Related

How to return an ordered string from an unordered one?

I am trying to solve a problem but struggling with the logic approach to it. The problem is as follows:
"Your task is to sort a given string. Each word in the string will contain a single number. This number is the position the word should have in the result.
Note: Numbers can be from 1 to 9. So 1 will be the first word (not 0).
If the input string is empty, return an empty string. The words in the input String will only contain valid consecutive numbers."
For e.g. "is2 Thi1s T4est 3a" --> "Thi1s is2 3a T4est"
I have tried the following so far:
def order(sentence):
my_string = "is2 Thi1s T4est 3a"
new_string = " "
for i in my_string:
if i in my_string == none
return new_string = " "
else:
if i in my_string
return new_string
But stuck on continuing the next bit. How can I put "put words into order starting from 1" into python code into my for loop?
I'm a beginner in python and programming so I am not entirely sure if the approach I'm making is the best logical way to do so, by creating an empty string new_string and then sorting my_string into that. Is this a good way of approaching this? I am stuck on which direction to go after this.
you could do :
r = "is2 Thi1s T4est 3a"
def get_number(w) :
for x in w :
try :
i = int(x)
return i
except :
pass
return None
ordered_list = " ".join((sorted( s.split(' ') , key = get_number)))
the function get_number allows to get the first number appearing in a word, so we split the sentence to get the words it's made of , r.split(' ') gives ['is2', 'Thi1s', 'T4est', '3a'], we order then the list using ordered builtin function , it takes a list and a function that yields the keys over which we want to order the list, and outputs the ordered list, we then use the builtin function join to join the list using a space separator.
Output :
Out[425]: 'Thi1s is2 3a T4est'

TypeError: 'int' object is not iterable. When iterating over each string in string data

good day,
My objective is to use .lower() for converting each string in the text data into the lower case. I tried to use .count() with a one-liner iteration. However, I get the following error:
TypeError: 'int' object is not iterable
Here is my code:
# Iterating over the strings in the data. The data is called text
text_lowercase = ''.join((string.lower().strip() for string in text.count(0,)))
I want to use the one-liner iteration and do this.
Help would be truly appreciated. Cheers!
text.count returns an integer. You try to iterate over it:
for string in text.count(0,)
but since it returns an integer, there is no in (it is not iterable). This is what the error message is telling you.
In the future, to better identify the source of an error, try to break up one-liners into multiple lines. This will give you better feedback on what part of your operation is failing.
There's a couple of issues to point out here:
text_lowercase = ''.join((string.lower().strip() for string in text.count(0,)))
Naming the temporary variable string is a bad idea, as this looks a lot like the type name. Something like s is more common and readable.
Or perhaps word because that's what you are after it seems. This is the second problem, your approach seems to break down the string in characters, but from the comments it appears you'd like to operate on words? (your use of strip also suggests this)
You're joining on '', which results in all the parts of the string being joined with no space between them.
As others point out, count returns an integer, but you want to operate on the actual string. You indicated you only tried count to iterate and that's not needed in Python like it is in many other languages.
Putting it together for words:
text_lowercase = ' '.join([w.lower() for w in text.split(' ')])
Or if you're after characters:
text_lowercase = ''.join([ch.lower() for ch in text])
But then you could just:
text_lowercase = text.lower()
Perhaps you like words, but want to get rid of excess spaces?
text_lowercase = ' '.join([w.lower() for w in text.split(' ') if w != ''])
Or in shorthand:
text_lowercase = ' '.join([w.lower() for w in text.split(' ') if w])
The exception you get is because the count() returns an int and then you try to iterate over that int. I think you should remove the count and you might be good to go (depending on how text looks like)
If you want to have a function that just lower cases the instances of string inside your text, maybe you can use something like this:
def lowercase_instance(text, string):
return string.lower().join(text.split(string))
Now, if you have a list of texts then you can do something like this:
lowercase_texts = [lowercase_instance(text, string) for text in texts]
hopefully this helps!

Python - Capture string with or without specific character

I am trying to capture the sentence after a specific word. Each sentences are different in my code and those sentence doesn't necessarily have to have this specific word to split by. If the word doesn't appear, I just need like blank string or list.
Example 1: working
my_string="Python is a amazing programming language"
print(my_string.split("amazing",1)[1])
programming language
Example 2:
my_string="Java is also a programming language."
print(my_string.split("amazing",1)[1]) # amazing word doesn't appear in the sentence.
Error: IndexError: list index out of range
Output needed :empty string or list ..etc.
I tried something like this, but it still fails.
my_string.split("amazing",1)[1] if my_string.split("amazing",1)[1] == None else my_string.split("amazing",1)[1]
When you use the .split() argument you can specify what part of the list you want to use with either integers or slices. If you want to check a specific word in your string you can do is something like this:
my_str = "Python is cool"
my_str_list = my_str.split()
if 'cool' in my_str_list:
print(my_str)`
output:
"Python is cool"
Otherwise, you can run a for loop in a list of strings to check if it finds the word in multiple strings.
You have some options here. You can split and check the result:
tmp = my_string.split("amazing", 1)
result = tmp[1] if len(tmp) > 1 else ''
Or you can check for containment up front:
result = my_string.split("amazing", 1)[1] if 'amazing' in my_string else ''
The first option is more efficient if most of the sentences have matches, the second one if most don't.
Another option similar to the first is
result = my_string.split("amazing", 1)[-1]
if result == my_string:
result = ''
In all cases, consider doing something equivalent to
result = result.lstrip()
Instead of calling index 1, call index -1. This calls the last item in the list.
my_string="Java is also a programming language."
print(my_string.split("amazing",1)[1])
returns ' programming language.'

a mistake I keep having with for loops and return statements

I have been noticing a problem I am having whenever I try to make a function that takes changes a string or a list then returns it.
I will give you an example of this happening with a code I just wrote:
def remove_exclamation(string):
string.split(' ')
for i in string:
i.split()
for char in i:
if char == '!':
del char
''.join(i)
' '.join(string)
return string
For instance, I create this code to take a string as its parameter, remove any exclamation in it, the return it changed. The input and output should look like this:
>>>remove_exclamation('This is an example!')
'This is an example'
But instead I get this:
>>>remove_exclamation('This is an example!')
'This is an example!'
The function is not removing the exclamation in the output, and is not doing what I intended for it to day.
How can I keep avoiding this when I make for loops, nested for loops etc?
You write your code and formulate your question as if it was possible to modify strings in Python. It is not possible.
Strings are immutable. All functions which operate on strings return new strings. They do not modify existing strings.
This returns a list of strings, but you are not using the result:
string.split(' ')
This also:
i.split()
This deletes the variable named char. It does not affect the char itself:
del char
This creates a new string which you do not use:
''.join(i)
This also:
' '.join(string)
All in all, almost every line of the code is wrong.
You probably wanted to do this:
def remove_exclamation(string):
words = string.split(' ')
rtn_words = []
for word in words:
word_without_exclamation = ''.join(ch for ch in word if ch != '!')
rtn_words.append(word_without_exclamation)
return ' '.join(rtn_words)
But in the end, this does the same thing:
def remove_exclamation(string):
return string.replace('!', '')
Without clearly knowing the intentions of your function and what you are attempting to do. I have an alternative to the answer that zvone gave.
This option is to remove any characters that you have not defined in an allowed characters list:
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "
test_string = "This is an example!"
test_string = ''.join(list(filter(lambda x: x in characters, test_string)))
print(test_string)
This outputs:
This is an example
Note, this is the Python 3 version.
Python 2, you do not need the ''.join(list())
Doing it this way would allow you to define any character that you do not want present in your string, and it will remove them.
You can even do the reverse:
ignore_characters= "!"
test_string = "This is an example!"
test_string = ''.join(list(filter(lambda x: x not in ignore_characters, test_string)))
print(test_string)
Strings are immutable in Python. And you cannot change them. You can however, re-assign there values.
That is where your problem lies. You never reassign the value of your strings, when you call .split() on them.
But there are also others errors in your program such as:
Your indention
The fact that your just returning the string thats passed into the function
Your use of the del statement
etc.
Instead, create a new string by iterating through the old one and filtering out the character(s) you do not want, via list comprehension and ''.join().
def remove_exclamation(string):
return ''.join([char for char in string if char != '!'])
But as #Moses has already said in the comments, why not just use str.replace()?:
string = string.replace('!', '')
def remove_exclamation(string):
#you think you are splitting string into tokens
#but you are not assigning the split anywhere...
string.split(' ')
#and here you are cycling through individual _chars_ in string which was not affected by the split above ;-)
for i in string:
#and now you are splitting a 1-char string and again not assigning it.
i.split()
And string is still your input param, which I assume is of type str. And immutable.
On top of which, if you were import/using the string module, you would be shadowing it
A big part of your confusion is knowing when the methods mutate the objects and when they return a new object. In the case of strings, they never mutate, you need to assign the results to a new variable.
On a list however, and the join() somewhere makes me think you want to use a list, then methods generally change the object in place.
Anyway, on to your question:
def remove_exclamation(inputstring, to_remove="!"):
return "".join([c for c in inputstring if c != to_remove])
print (remove_exclamation('This is an example!'))
output:
This is an example

How to print random items from a dictionary?

everyone. I'm trying to complete a basic assignment. The program should allow a user to type in a phrase. If the phrase contains the word "happy" or "sad", that word should then be randomly replaced by a synonym (stored in a dictionary). The new phrase should then be printed out. What am I doing wrong? Every time I try to run it, the program crashes. This is the error I get:
0_part1.py", line 13, in <module>
phrase["happy"] = random.choice(thesaurus["happy"])
TypeError: 'str' object does not support item assignment
Here is what I have so far:
import random
thesaurus = {
"happy": ["glad", "blissful", "ecstatic", "at ease"],
"sad": ["bleak", "blue", "depressed"]
}
phrase = input("Enter a phrase: ")
phrase2 = phrase.split(' ')
if "happy" in phrase:
phrase["happy"] = random.choice(thesaurus["happy"])
if "sad" in phrase:
phrase["sad"] = random.choice(thesaurus["sad"])
print(phrase)
The reason for your error is that phrase is a string, and strings are immutable. On top of that, strings are sequences, not mappings; you can index them or slice them (e.g., happy_index = phrase.find("happy"); phrase[happy_index:happy_index+len("happy")]), but you can't use them like dictionaries.
If you want to create a new string, replacing the substring happy with another word, use the replace method.
And there's no reason to check first; if happy isn't found, replace wil do nothing.
So:
phrase = phrase.replace("happy", random.choice(thesaurus["happy"]))
While we're at it, instead of explicitly looking up each key, you may want to loop over the dictionary and apply all the synonyms:
for key, replacements in thesaurus.items():
phrase = phrase.replace(key, random.choice(replacements))
Finally, notice that this code will replace all instances of happy with the same replacement. Which I think your intended code was also trying to do. If you want to replace each of them with a separately randomly-chosen synonym, that's a bit more complicated. You could loop over phrase.find("happy", offset) until it returns -1, but a neat trick might make it simpler: split the string around each instance of happy, substitute in a different synonym for each split part, then join them all back together. Like this:
parts = phrase.split("happy")
parts[:-1] = [part + random.choice(thesaurus["happy"]) for part in parts[:-1]]
phrase = ''.join(parts)
Generate a random number from (0..[size of list - 1]). Then, access that index of the list. To get the length of a list, just do len(list_name).

Categories

Resources