Concatenate letter to a string with for loop - python

I wanted to create a for-loop which will check the items on a list, and if condition is met,
a letter will be added every time to a string.
This is what I made:
words = 'bla bla 123 554 gla gla 151 gla 10'
def checkio(words):
for i in words.split():
count = ''
if isinstance(i, str) == True:
count += "k"
else:
count += "o"
My supposed to be count result is 'kkookkoko' (5 times cause of 5 strings).
what I get from this function is that count = 'k'.
why does the letters do not concatenate through my for loop?
Please help!
Regards..!

It is because you are setting count to '' on each iteration, that line should be outside:
count = ''
for ...:
Also, you can just do
if isinstance(i, str):
it's not necessary to compare with == True, because isinstance returns a boolean.
With your code you will always get a string full of k. Why? Because words.split() will return a list of strings, therefore, the if will always be True.
How can you solve it? You can use a try-except block:
def checkio(words):
count = ''
for i in words.split():
try: # try to convert the word to an integer
int(i)
count += "o"
except ValueError as e: # if the word cannot be converted to an integer
count += "k"
print count

You are resetting count to be the empty string at each start of the loop. Put count='' before the for loop.
Other problems with your code: there's no return value for your function, the code lacks indentation, the == True part is obsolete. Also words.split() will only work if words is a string - and in that case, isinstance(i, str) will always be true.

Related

identifying the substring when the number of characters in between don't matter

def checkPattern(x, string):
e = len(string)
if len(x) < e:
return False
for i in range(e - 1):
x = string[i]
y = string[i + 1]
last = x.rindex(x)
first = x.index(y)
if last == -1 or first == -1 or last > first:
return False
return True
if __name__ == "__main__":
x = str(input())
string = "hello"
if checkPattern(x, string) is True:
print('YES')
if checkPattern(x, string) is False:
print('NO')
So basically the code is supposed to identify a substring when the number of characters between the substring's letters don't matter. string = "hello" is supposed to be the substring. While the characters in between don't matter the order still matters so If I type "h.e.l.l.o" for example it's a YES, but if it's something like "hlelo" it's a NO. I sorta copied the base of the code and I'm still a little new to python so sorry if the question and code aren't clear.
Assuming I understand, and the input hlelo is No and the input h.e..l.l.!o is Yes, then the following code should work:
def checkPattern(x, string):
assert x and string, "Error. Both inputs should be non-empty. "
count_idx = 0 # index which counts where you are.
for letter in x:
if letter == string[count_idx]:
count_idx += 1 # increment to check the next string
if count_idx == len(string):
return True
# pattern was found if counter found matches equal to string length
return False
if __name__ == "__main__":
inp = input()
string = "hello"
if checkPattern(inp, string) is True:
print('YES')
if checkPattern(inp, string) is False:
print('NO')
Explaination: Regardless of the input string, x, you want to loop through each character of the search-string hello, to check if you find each character in the correct order. What my solution does is that it counts how many of the characters h, e, l, l, o it has found, starting from 0. If it finds a match for h, it moves on to check for a match for e, and so on. Ultimately, if you search through the entire string x, and the counter does not equal to the length of the search string (i.e. you could not find all the hello characters), it returns false.
EDIT: Small debug in the way the return worked. Instead returns if ever the counter goes over the length. Also added more examples given in comments
Here is my solution to this problem:
pattern = "hello"
def patternCheck(word, pattern) -> bool:
plist = list(pattern)
wlist = list(word)
for p in plist:
if p in wlist:
for _ in range(wlist.index(p) , -1, -1):
wlist.pop(_)
else:
return False
return True
print(patternCheck("h.e.l.l.o", pattern))
print(patternCheck("aalohel", pattern))
print(patternCheck("hhhhheeelllooo", pattern))
Explanation
First we convert our strings to a list
plist = list(pattern)
wlist = list(word)
Now we check using a for loop if every element in our pattern list is in the word list.
for p in plist:
if p in wlist:
If yes then we remove all the elements from index 0 to the index of that element.
for _ in range(wlist.index(p) , -1, -1):
wlist.pop(_)
We are removing elements in decreasing order of there indices to protect ourself from the IndexError: pop index out of range.
If the for loop ends normally then there was a match and we return True. Else if the element was not found in the word list in the first place then we return false as there is no match.

String Index out of range issue while making a function that counts vowels

I am trying to make a function that counts all the vowels using recursion and I keep getting string index out of range.
def vowels(s):
vowel = "AEIOUaeiou"
if s == " ":
return 0
if s[0] in vowel:
return 1 + vowels(s[1:])
else:
return vowels(s[1:])
print(vowels("Hello Planet Me"))
I am expecting a number of vowels in a string and I just get error on lines 8 and 10 repeating.
Change this line
if s == " ":
to
if s == "":
or
if len(s) == 0:
or, the best way is to use the boolean value of str type in python which returns a False if the str is empty.
if not s:
For the base case, an empty string is passed to the function and not a space character.
if you just change your initial if condition to
if not s:
return 0
you will be fine. that way you just return 0 if the string is empty an you do not get to the line containing s[1:] (which will raise the error you encountered).
a simple non-recursive way would be:
VOWELS = set("AEIOUaeiou")
def vowels(s):
return sum(char in VOWELS for char in s)
(as True is just an alias for 1 and False is an alias for 0 you can just sum the booleans).

How to make a for loop iterate through each item in a string with an if statement?

I'm trying to make a function that takes in a string from a user and then outputs the same string. However for each letter in an even position it outputs the corresponding lower case letter, and for each letter in an odd position it outputs the corresponding uppercase letter. Keep in mind only one word will be passed through it at a time.
I've tried to create a for loop with an if statement nested within it, but so far, the for loop stops after iterating through the first letter. My code is below:
def converter(string):
for letters in string:
if len(letters) % 2 == 0:
return letters.lower()
elif len(letters)% 2 != 0:
return letters.upper()
When I run the code:
converter('app')
The output I get is 'A'
The expected output should be 'aPp'
The first thing you need to know is that in Python, strings are immutable. So "modifying" a string means you have to build a new string from scratch in (here, I call that newstring).
Second, you are misunderstanding the loop. You are saying for letters in string. This loop iterates over each letter of the string. On the first iteration, letters is the first letter of the strong. You then convert it to upper case (since the length of a single letter is always 1), and return it. You aren't reaching the rest of the letters! In the code below, I change the plurality to just letter to make this idea clear.
This amends all of those problems:
def converter(string):
newstring = ""
for i, letter in enumerate(string):
if i % 2 == 0:
newstring += letter.lower()
elif i % 2 != 0:
newstring += letter.upper()
return newstring
This can be boiled down to a nice list comprehension:
def converter(string):
return "".join([letter.lower() if i % 2 == 0 else letter.upper()
for i, letter in enumerate(string)])
In [1]: def converter(string):
...: return ''.join([j.upper() if i % 2 == 1 else j.lower() for i, j in enumerate(string)])
In [2]: converter('apple')
Out[2]: 'aPpLe'
''.join([s.lower() if c % 2 == 0 else s.upper() for c, s in enumerate('apple')])
# returns 'aPpLe'
first check for the condition, then iterate through the string using the nice old enumerate built-in.

Code is not validating: TypeError cannot concatenate 'str' and 'int' objects

While loops are new to me and I'm having trouble getting my code to validate.
Description
In this exercise your function will receive two parameters: a
string(long_word) and a character(char). Use a while loop to go
through all the letters in the string and build a new string made up
from those letters until you find the char. You may assume that each
string will contain the passed in character(char).
This is my code.
def letters_up_to_char(long_word, char):
new = ""
i = 0
while i != char:
for letter in long_word:
new += letter
i += 1
return new
Example output
letters_up_to_char('coderoxthesox', 'x') -> 'codero'
letters_up_to_char('abcdefghijklmnop', 'f') -> 'abcde'
When I go to run my code I get:
TypeError: cannot concatenate 'str' and 'int' objects
To get rid of TypeError: cannot concatenate 'str' and 'xyz' objects, just
cast the object being concatenated to a string. If your code was
string + num or string += num just cast num to string like so:
str(num)
BUT, your code won't return the desired output. See why below:
If I'm not mistaken, the code shouldn't compile because when new is defined, you don't close the double quotes. Or if you are using single quotes, change your code and your question to reflect your change.
When I ran your code and executed it, it went in an infinite loop, the beginner's worst enemy! In your code, the
for letter in long_word:
new += letter
Is the same as saying new += long_word, because you are just adding the individual characters instead of the whole string at one go.
Your code can then be rewritten as follows:
def letters_up_to_char(long_word, char):
new = ""
i = 0
while i != char:
new += long_word
i += 1
return new
Now it is clear what your code is doing. It's just adding the whole word to new each time the while loop is executed. And the while loop is executed till i != char. Since i is an int and char is a str, i != char is always true. Infinite loop in the making!
Your function should look like this:
def letters_up_to_char(long_word, char):
new = ""
i = 0
while i < len(long_word) and long_word[i] != char:
new += long_word[i]
i += 1
return new
Explanation:
Go through each character in long_word from the start (this can be more easily accomplished using a for...in loop, but I'm using a while loop as per your request) and till the current character != char, add that character to new.
This code returns the desired output for both your test cases.
Considering
You may assume that each string will contain the passed in
character(char).
not including the char:
def letters_up_to_char(long_word, char):
i=0
while long_word[i] != char:
i+=1
return long_word[:i]
including the char:
def letters_up_to_char(long_word, char):
i=0
while long_word[i] != char:
i+=1
return long_word[:i+1]
Though a more pythonic way is, i.e.:
def letters_up_to_char(long_word, char):
return long_word.partition(char)[0]
Suggest you to use http://docs.python.org/3/tutorial/index.html as a reference, when completing your assignments.
The "i" is int type which cannot be compared with a str type "char".
while i < len(long_word) and long_word[i] != char
There are a couple of ways similar to this to write this code. In your example, the while i != char line is going to result in a very long loop because it will loop until i == int(char), or possibly infinitely. I would write it with either a for or a while, as below:
def letters_while(long_word, char):
new = ""
i = 0
# A second condition is needed to prevent an infinite loop
# in the case that char is not in long_word
while long_word[i] != char and i < len(long_word):
new += letter
i += 1
return new
def letters_for(long_word, char):
new = ""
for letter in long_word:
if letter != char:
new += letter
return new
As a note, these are easy to understand examples, and a better way to do this would be
long_word.split(char)[0]

Finding the number of occurences of a sub-string in a string without using library functions

I have to do this exercise without using library function. So far I have reached here:-
string = input("Enther The String :")
substring = input("Enter the substring :")
count = 0
for i in range(len(string)):
if string[i:i+len(substring)] == substring:
if string[i+len(substring)] == ' ':
count += 1
else:
count = 0
print(count)
But, let us say if the sub-string is 'bob' and the string is 'bob cat bob cat bobs cat', the program still counts 'bob' in 'bobs' and I don't want that. Also this code always returns 0. Please help! Thanks!
the program still counts 'bob' in 'bobs'
It doesn't.
Also this code always returns 0
This is because of your else clause.
else:
count = 0
You're resetting the count here. That's not what you want; if the next character isn't a space, you don't want to do anything at all. Remove the whole else clause.
You have an additional bug you haven't noticed. If string ends with substring, the following test:
if string[i+len(substring)] == ' ':
will attempt to read past the end of the string and throw an IndexError. Try to solve this problem on your own first.
As you're allowed to use slicing, so you can use that to check whether the character before/after the substring is a space or empty string, if it is then increment count by 1. Note that slices never raise exception, even for out of range indices.
def sub_str_count(s, sub_str):
le = len(sub_str)
count = 0
for i in range(len(s)):
if s[i:i+le] == sub_str and s[i-1:i] in ('', ' ') and \
s[i+le:i+le+1] in ('', ' '):
count += 1
return count
Exception handling based version of the above code:
def check(s, ind):
"""
Check whether the item present at this index is a space or not.
For out of bound indices return True.
For negative indices return True.
"""
if ind < 0:
return True
try:
return s[ind] == ' '
except IndexError:
return True
def sub_str_count(s, sub_str):
le = len(sub_str)
count = 0
for i in range(len(s)):
if s[i:i+le] == sub_str and check(s, i-1) and check(s, i+le):
count += 1
return count

Categories

Resources