I have a string str1 = "This is Kane and Kane is a coder" and another string str2 = "tsk"
Now i want to remove all the characters of str2 which are appearing in str1 and store in another variable say word1
The result im expecting is
str1 = "hi i ane and ane i a coder"
word1 = TssKKs
word1 = ''
for i in str2:
if i in str1.lower():
word1 += i
str1 = str1.lower().replace(i,'')
I guess this is not very optimised method as im running a loop for each character of str2 which will affect the time for long strings
In your example code, for every letter in str2, it needs to iterate over str1 2 times: in the line if i in str1.lower() and in str1.replace(i,''). This means 6 times in in the example.
The following solution only iterates over str1 once and the check against a set is fast. It builds 2 new strings in parallel in one pass.
str1 = "This is Kane and Kane is a coder"
str2 = "tsk"
word = ""
new_str = ""
remove = set(str2)
for letter in str1:
if letter.lower() in remove:
word += letter
else:
new_str += letter
print(word)
print(new_str)
I mean in order to get the correct order and capitalization of word1 you probably need to loop over str1, so:
new_str1 = ""
word1 = ""
for c in str1:
if c in set(str2):
word1 += c
else:
new_str1 +=c
And if capitalization don't matter.
well word1 = set(str2) and
import re
str1 = re.sub("[tsK]","", str1)
For short string like str2 the algorithm would not affect the performance and an optimisation would be exaggerating. Still, as it is short you can get rid of the inner loop and use an if statement instead. And you don't need to call lower in each loop. Just call it before entering the for:
word1 = ''
str1 = str1.lower()
for i in str1:
if i == "t" or i == "s" or i == "k":
word1 += i
str1 = str1.replace(i,'')
This should be way faster as the other letters are not tested against once one condition has evaluated to true.
And as #jarmod said, no need to convert a str to list, as str is iterable.
EDIT: for a case sensitive letters in word1, you need to use a temp variable:
word1 = ''
str1_low = str1.lower()
count = 0
for i in str1_low:
count = count + 1
if i == "t" or i == "s" or i == "k":
word1 += str1[count]
str1 = str1[:count] + str1[count+1:]
Related
I'm trying to make a program that will convert any text into a different form. That means that a text such as 'hi there' becomes 'hI tHeRe'.
list = []
word = input('Enter in a word or a sentence! ')
for num in range(len(word)):
list.clear()
list.append('i')
letter = word[num]
for x in range(len(list)):
if x % 2 == 0:
i = word.index(letter)
place = letter.lower()
word = word.replace(word[i], place)
if not x % 2 == 0:
i = word.index(letter)
place = letter.upper()
word = word.replace(word[i], place)
print(word)
However, when I run the code it just prints the same string as normal.
When using replace, you have to assign the result to your variable:
word = word.replace(word[i], place)
However, replace is actually not what you want here. replace replaces all instances of a certain pattern with a new string. In your current code, every instance of whatever letter word[i] represents will be replaced with the result of .lower() or .upper().
You also don't want to use the word list, since doing so will shadow the Python built-in list class.
If you want to keep most of your original logic, you can follow #khelwood's suggestion in the comments and end up with the following:
word = input('Enter in a word or a sentence! ')
wordList = list(word)
for i in range(len(word)):
if i % 2 == 0:
wordList[i] = word[i].lower()
else:
wordList[i] = word[i].upper()
print(''.join(wordList))
Here is one of my previous codes, you can change all the variable names to whatever you see fit.
s = input('Enter in a word or string.')
ret = ""
i = True # capitalize
for char in s:
if i:
ret += char.upper()
else:
ret += char.lower()
if char != ' ':
i = not i
print(ret)
I hope it works for you.
Try this one liner -
a = 'hi there'
''.join([i[1].lower() if i[0]%2==0 else i[1].upper() for i in enumerate(a)])
'hI ThErE'
If you care about each word starting from lowercase then this nested list comprehension works -
' '.join([''.join([j[1].lower() if j[0]%2==0 else j[1].upper() for j in enumerate(i)]) for i in a.split()])
'hI tHeRe'
The problem is with list.clear in the beginning of the for loop.
Each iteration you clear the list so the second for iteration run on the first item only.
Remove list.clear and it should scan the input word
consider examples below :
Example 1 :
str1 = "wow...it looks amazing"
str2 = "looks amazi"
You see that amazi is close to amazing, str2 is mistyped, i wanted to write a program that will tell me that amazi is close to amazing then in str2 i will replace amazi with amazing
Example 2 :
str1 = "is looking good"
str2 = "looks goo"
In this case updated str2 will be "looking good"
Example 3 :
str1 = "you are really looking good"
str2 = "lok goo"
In this case str2 will be "good" as lok is not close to looking (or even if program can convert in this case lok to looking then it's just fine for my problem's solution)
Example 4 :
str1 = "Stu is actually SEVERLY sunburnt....it hurts!!!"
str2 = "hurts!!"
Updated str2 will be "hurts!!!"
Example 5 :
str1 = "you guys were absolutely amazing tonight, a..."
str2 = "ly amazin"
Updated str2 will be "amazing", "ly" shall be removed or replace by absolutely.
What will be the algo and code for this?
Maybe we can do it by looking at character lexicographically and set a
threshold like 0.8 or 80% so if word2 gets 80% sequential characters of word1 from str1 then we replace word2 in str2 with word of str1?
Any other efficient solution with python code please?
There are a lot of ways to approach this. This one solves all of your examples. I added a minimum similarity filter to return only the higher quality matches. This is what allows the 'ly' to be dropped in the last sample, as it is not all that close any any of the words.
Documentation
You can install levenshtein with pip install python-Levenshtein
import Levenshtein
def find_match(str1,str2):
min_similarity = .75
output = []
results = [[Levenshtein.jaro_winkler(x,y) for x in str1.split()] for y in str2.split()]
for x in results:
if max(x) >= min_similarity:
output.append(str1.split()[x.index(max(x))])
return output
Each sample you proposed.
find_match("is looking good", "looks goo")
['looking','good']
find_match("you are really looking good", "lok goo")
['looking','good']
find_match("Stu is actually SEVERLY sunburnt....it hurts!!!", "hurts!!")
['hurts!!!']
find_match("you guys were absolutely amazing tonight, a...", "ly amazin")
['amazing']
Like this:
str1 = "wow...it looks amazing"
str2 = "looks amazi"
str3 = []
# Checking for similar strings in both strings:
for n in str1.split():
for m in str2.split():
if m in n:
str3.append(n)
# If found 2 similar strings:
if len(str3) == 2:
# If their indexes align:
if str1.split().index(str3[1]) - str1.split().index(str3[0]) == 1:
print(' '.join(str3))
elif len(str3) == 1:
print(str3[0])
Output:
looks amazing
UPDATE with condition given by the OP:
str1 = "good..."
str2 = "god.."
str3 = []
# Checking for similar strings in both strings:
for n in str1.split():
for m in str2.split():
# Calculating matching character in the 2 words:
c = ''
for i in m:
if i in n:
c+=i
# If the amount of matching characters is greater or equal to 50% the length of the larger word
# or the smaller word is in the larger word:
if len(list(c)) >= len(n)*0.50 or m in n:
str3.append(n)
# If found 2 similar strings:
if len(str3) == 2:
# If their indexes align:
if str1.split().index(str3[1]) - str1.split().index(str3[0]) == 1:
print(' '.join(str3))
elif len(str3) == 1:
print(str3[0])
I made through it with regular expressions
def check_regex(str1,str2):
#New list to store the updated value
str_new = []
for i in str2:
# regular expression for comparing the strings
x = ['['+i+']','^'+i,i+'$','('+i+')']
for k in x:
h=0
for j in str1:
#Conditions to make sure the word is close enough to the particular word
if "".join(re.findall(k,j)) == i or ("".join(re.findall(k,j)) in i and abs(len("".join(re.findall(k,j)))-len(i)) == 1 and len(i)!=2):
str_new.append(j)
h=1
break
if h==1:
break
return str_new
import re
str1 = input().split()
str2 = input().split()
print(" ".join(check_regex(str1,str2)))
You can use Jacard coefficient in this case. First, you need to split your first and second string by space. After that, for every string in str2, take Jacard coefficient with every string in str1, then replace with which that gives you the highest Jacard coefficient.
You can use sklearn.metrics.jaccard_score.
Okey so basically I have to check if one string has the same letters of another string. Both strings are obtained via input().
I don't want to double check if a letter is in the other string, so if I already checked that letter I want to skip to the next letter.
The code I have for now is this:
str1, str2 = list(input()), list(input())
if len(str1) > len(str2):
str = str1
else:
str = str2
for x in str:
c = 0
if x in str2:
c += 1
if c != 0:
print("Both have the same letters!")
else:
print("Nope there are some letters missing..")
I don't know if I should work with the lists instead of using a counter.. please a detailled explanation of the solution or some good quality guidance would be very appreciated! <3
Converting strings to sets of individual symbols remove duplicate symbols, so we can simply compare them:
if set(str1) == set(str2):
print("Both have the same letters!")
else:
print("Nope there are some letters missing..")
Note:
As the order of elements in sets is not important, we may even compare them, e. g.
if set(str1) <= set(str2): # <= means "is subset" in this context
print("All symbols in str1 are in str2, too.")
or
if set(str1) < set(str2): # < means "is a proper subset" in this context
print("All symbols in str1 are in str2, too, "
"but str2 has at least 1 symbol not contained in str1.")
Some issues with the code are that, str2 is always used for comparison even if str2 is longer than str1
for x in str:
c = 0
if x in str2:
Next, c is set to 0 for every character in str, Instead you can have a counter to count the number of chars not in the other string
This should do the job
str1, str2 = list(input()), list(input())
if len(str1) > len(str2):
str = str1
compared_string = str2
else:
str = str2
compared_string = str1
not_in_other_string = 0
for x in str:
if x not in compared_string:
not_in_other_string += 1
if not_in_other_string == 0:
print("Both have the same letters!")
else:
print("Nope there are some letters missing..")
It sounds like you want to find if all of the characters in one string are in some larger string.
You could use unique = ''.join(set(substring)) to get a list of chars in the substring and then make a list comprehension to get all the chars in the larger string.
Here is my example:
unique = ''.join(set(substring))
not_in = [char for char in unique if char not in superstring]
Now you can check not_in to see if it is null, otherwise there was a char in the substring that was not in the superstring.
For example:
superstring = "hello"
substring = "xllo"
unique = ''.join(set(substring))
not_in = [char for char in unique if char not in superstring]
print not_in
>>>['x']
print not_in == []
>>>False
Typically, the preferred way to do things in python is using list comprehensions or use some built in function that already checks strings for you, rather than the C style where you go through a loop and check letter for letter explicitly. This is the idiomatic way of pythonic programming.
Breaking apart the list comprehension we have a loop like this:
for char in unique:
if char not in superstring:
char #char meets conditions so it is the value used in [char ...
Here would be the modification I would make
str1, str2 = input(), input()
unique = ''.join(set(str1))
not_in = [char for char in unique if char not in str2]
if not_in == []:
print("Both have the same letters!")
else:
print("Nope there are some letters missing..")
str1, str2 = input().split()
if len(str1) > len(str2):
string_to_check= str1
string_from_which_to_check = str2
else:
string_to_check = str2
string_from_which_to_check = str1
not_in_other_string = set(string_to_check) - set(string_from_which_to_check)
if len(not_in_other_string )==0:
print("character are present in string")
else:
print("{} not present in string".format(str(not_in_other_string )))
So I was doing our exercise when I came across capitalizing characters in odd indices. I tried this:
for i in word:
if i % 2 != 0:
word[i] = word[i].capitalize()
else:
word[i] = word[i]
However, it ends up showing an error saying that not all strings can be converted. Can you help me debug this code snippet?
The problem is strings in python are immutable and you cannot change individual characters. Apart fro that when you iterate through a string you iterate over the characters and not the indices. So you need to use a different approach
A work around is
(using enumerate)
for i,v in enumerate(word):
if i % 2 != 0:
word2+= v.upper()
# Can be word2+=v.capitalize() in your case
# only as your text is only one character long.
else:
word2+= v
Using lists
wordlist = list(word)
for i,v in enumerate(wordlist):
if i % 2 != 0:
wordlist[i]= v.upper()
# Can be wordlist[i]=v.capitalize() in your case
# only as your text is only one character long.
word2 = "".join(wordlist)
A short note on capitalize and upper.
From the docs capitalize
Return a copy of the string with its first character capitalized and the rest lowercased.
So you need to use upper instead.
Return a copy of the string with all the cased characters converted to uppercase.
But in your case both work accurately. Or as Padraic puts it across "there is pretty much no difference in this example efficiency or output wise"
You need enumerate and capitalise any character at any odd i where i is the index of each char in the word:
word = "foobar"
print("".join( ch.upper() if i % 2 else ch for i, ch in enumerate(word)))
fOoBaR
ch.upper() if i % 2 else ch is a conditional expression where we change the char if the condition is True or else leave as is.
You cannot i % 2 when i is the actual character from the string, you would need to use range in your code or use enumerate and concatenate the changed characters to an output string or make words a list.
Using a list you can use assignment:
word = "foobar"
word = list(word)
for i, ele in enumerate(word):
if i % 2:
word[i] = ele.upper()
print("".join(word))
Using an output string:
word = "foobar"
out = ""
for i, ele in enumerate(word):
if i % 2:
out += ele.upper()
else:
out += ele
if i % 2: is the same as writing if i % 2 != 0.
This is how I would change word letters in a word or a sentence to uppercase
word = "tester"
letter_count = 1
new_word = []
for ch in word:
if not letter_count % 2 == 0:
new_word.append(ch.upper())
else:
new_word.append(ch)
letter_count += 1
print "".join(new_word)
if I wanted to change odd words in a sentence to uppercase I would do this
sentence = "this is a how we change odd words to uppercase"
sentence_count = 1
new_sentence = []
for word in sentence.split():
if not sentence_count % 2 == 0:
new_sentence.append(word.title() + " ")
else:
new_sentence.append(word + " ")
sentence_count += 1
print "".join(new_sentence)
I think it will help...
s = input("enter a string : ")
for i in range(0,len(s)):
if(i%2!=0):
s = s.replace(s[i],s[i].upper())
print(s)
I Am writing a function that should take a string input and return the string with every first letter of every word as a capital letter, I have achieved this to a certain degree.
My Code:
string = input("Please Enter A string:")
def capitalize_words(string):
split = string.split()
letter1 = ''
letter2 = ''
letter3 = ''
str1 = split[0]
str2 = split[1]
str3 = split[2]
for i in str1:
if i in str1[0]:
first = i.upper()
else:
letter1 = letter1 + i
string1 = (first+letter1)
for i in str2:
if i in str2[0]:
first = i.upper()
else:
letter2 = letter2 + i
string2 = (first+letter2)
for i in str3:
if i in str3[0]:
first = i.upper()
else:
letter3 = letter3 + i
string3 = (first+letter3)
result = string1+' '+string2+' '+string3
return result
func = capitalize_words(string)
print(func)
Input:
Please Enter A string:herp derp sherp
Output:
Herp Derp Sherp
However this is very inflexible because i can only enter 3 words with spaces no more no less , this makes for a rather primal program. I would like to be able to enter anything and get the desired result of the first letter of every word being a capital letter no matter how many words i enter.
I fear with my skills this is as far as I am able to get, can you please improve my program if possible.
>>> print(raw_input('Please Enter A string: ').title())
Please Enter A string: herp derp sherp
Herp Derp Sherp
Use str.title() to achieve what you want in one go.
But to process words in a sentence, use a loop instead of a series of local variables; here is a version that does the same what you are doing for an arbitrary number of words:
for i, word in enumerate(split):
split[i] = word[0].upper() + word[1:]
result = ' '.join(split)
I used string slicing as well to select just the first character, and all but the first character of a word. Note the use of enumerate() to give us a counter which wich we can replace words in the split list directly.
An alternative method is to use re.sub such as:
re.sub(r'\b.', lambda c: c.group().upper(), 'herp derp sherp and co.')
# 'Herp Derp Sherp And Co.'
You could write this in a one-line generator expression:
def upper_case(text):
return ' '.join(w[0].upper() + w[1:] for w in text.split())
Notice, that this function fails on single letter words and replaces any whitespace by a single space character.
Use this as
In [1]: upper_case(input('Please Enter A string: '))
Please Enter A string: hello world
Out[1]: 'Hello World'