Find out word at specific index - python

I have a string with multiple words separated by underscores like this:
string = 'this_is_my_string'
And let's for example take string[n] which will return a letter.
Now for this index I want to get the whole word between the underscores.
So for string[12] I'd want to get back the word 'string' and for string[1] I'd get back 'this'

Very simple approach using string slicing is to:
slice the list in two parts based on position
split() each part based on _.
concatenate last item from part 1 and first item from part 2
Sample code:
>>> my_string = 'this_is_my_sample_string'
# ^ index 14
>>> pos = 14
>>> my_string[:pos].split('_')[-1] + my_string[pos:].split('_')[0]
'sample'

This shuld work:
string = 'this_is_my_string'
words = string.split('_')
idx = 0
indexes = {}
for word in words:
for i in range(len(word)):
idx += 1
indexes[idx] = word
print(indexes[1]) # this
print(indexes[12]) #string

The following code works. You can change the index and string variables and adapt to new strings. You can also define a new function with the code to generalize it.
string = 'this_is_my_string'
sp = string.split('_')
index = 12
total_len = 0
for word in sp:
total_len += (len(word) + 1) #The '+1' accounts for the underscore
if index < total_len:
result = word
break
print result

A little bit of regular expression magic does the job:
import re
def wordAtIndex(text, pos):
p = re.compile(r'(_|$)')
beg = 0
for m in p.finditer(text):
#(end, sym) = (m.start(), m.group())
#print (end, sym)
end = m.start()
if pos < end: # 'pos' is within current split piece
break
beg = end+1 # advance to next split piece
if pos == beg-1: # handle case where 'pos' is index of split character
return ""
else:
return text[beg:end]
text = 'this_is_my_string'
for i in range(0, len(text)+1):
print ("Text["+str(i)+"]: ", wordAtIndex(text, i))
It splits the input string at '_' characters or at end-of-string, and then iteratively compares the given position index with the actual split position.

Related

Replace sequence of the same letter with single one

I am trying to replace the number of letters with a single one, but seems to be either hard either I am totally block how this should be done
So example of input:
aaaabbcddefff
The output should be abcdef
Here is what I was able to do, but when I went to the last piece of the string I can't get it done. Tried different variants, but I am stucked. Can someone help me finish this code?
text = "aaaabbcddefff"
new_string = ""
count = 0
while text:
for i in range(len(text)):
l = text[i]
for n in range(len(text)):
if text[n] == l:
count += 1
continue
new_string += l
text = text.replace(l, "", count)
break
count = 0
break
Using regex
re.sub(r"(.)(?=\1+)", "", text)
>>> import re
>>> text = "aaaabbcddefff"
>>> re.sub(r"(.)(?=\1+)", "", text)
abcdeaf
Side note: You should consider building your string up in a list and then joining the list, because it is expensive to append to a string, since strings are immutable.
One way to do this is to check if every letter you look at is equal to the previous letter, and only append it to the new string if it is not equal:
def remove_repeated_letters(s):
if not s: return ""
ret = [s[0]]
for index, char in enumerate(s[1:], 1):
if s[index-1] != char:
ret.append(char)
return "".join(ret)
Then, remove_repeated_letters("aaaabbcddefff") gives 'abcdef'.
remove_repeated_letters("aaaabbcddefffaaa") gives 'abcdefa'.
Alternatively, use itertools.groupby, which groups consecutive equal elements together, and join the keys of that operation
import itertools
def remove_repeated_letters(s):
return "".join(key for key, group in itertools.groupby(s))

split a string to have chunks containing the maximum number of possible characters

e.g. string = 'bananaban'
=> ['ban', 'anab', 'an']
My attempt:
def apart(string):
letters = []
for i in string:
while i not in letters:
letters.append(i)
print("The letters are:" +str(letters))
x = []
result = []
return result
string = str(input("Enter string: "))
print(apart(string)
Basically, If I know all the letters that are in the word/string, I want to add them into x, until x contains all letters. Then I want to add x into result.
In my examaple "bananaban" it would mean [ban] is one x, because "ban" countains the letter "b","a" and "n". Same goes for [anab]. [an] only contains "a" and "n" because it is the end of the word.
Would be cool if somebody could help me ^^
IIUC, you want to split after all characters are in the current chunk.
You could use a set to keep track of the seen characters:
s = 'bananaban'
seen = set()
letters = set(s)
out = ['']
for c in s:
if seen != letters:
out[-1] += c
seen.add(c)
else:
seen = set(c)
out.append(c)
output: ['ban', 'anab', 'an']
The logical way seens to be first create a set with all letters in your string, then go over teh original one, collecting each character, and startign a new collection each time the set of letters in the collection match the original.
def apart(string):
target = set(string)
result = []
component = ""
for char in string:
component += char
if set(component) == target:
result.append(component)
component = ""
if component:
result.append(component)
return result
Using a set of the characters in the string, you can loop through the string and add or extend the last group in your resulting list:
S = "bananaban"
chars = set(S) # distinct characters of string
groups = [""] # start with an empty group
for c in S:
if chars.issubset(groups[-1]): # group contains all characters
groups.append(c) # start a new group
else:
groups[-1] += c # append character to last group
print(groups)
['ban', 'anab', 'an']

Split a string, loop through it character by character, and replace specific ones?

I'm working on an assignment and have gotten stuck on a particular task. I need to write two functions that do similar things. The first needs to correct capitalization at the beginning of a sentence, and count when this is done. I've tried the below code:
def fix_capitalization(usrStr):
count = 0
fixStr = usrStr.split('.')
for sentence in fixStr:
if sentence[0].islower():
sentence[0].upper()
count += 1
print('Number of letters capitalized: %d' % count)
print('Edited text: %s' % fixStr)
Bu receive an out of range error. I'm getting an "Index out of range error" and am not sure why. Should't sentence[0] simply reference the first character in that particular string in the list?
I also need to replace certain characters with others, as shown below:
def replace_punctuation(usrStr):
s = list(usrStr)
exclamationCount = 0
semicolonCount = 0
for sentence in s:
for i in sentence:
if i == '!':
sentence[i] = '.'
exclamationCount += 1
if i == ';':
sentence[i] = ','
semicolonCount += 1
newStr = ''.join(s)
print(newStr)
print(semicolonCount)
print(exclamationCount)
But I'm struggling to figure out how to actually do the replacing once the character is found. Where am I going wrong here?
Thank you in advance for any help!
I would use str.capitalize over str.upper on one character. It also works correctly on empty strings. The other major improvement would be to use enumerate to also track the index as you iterate over the list:
def fix_capitalization(s):
sentences = [sentence.strip() for sentence in s.split('.')]
count = 0
for index, sentence in enumerate(sentences):
capitalized = sentence.capitalize()
if capitalized != sentence:
count += 1
sentences[index] = capitalized
result = '. '.join(sentences)
return result, count
You can take a similar approach to replacing punctuation:
replacements = {'!': '.', ';': ','}
def replace_punctuation(s):
l = list(s)
counts = dict.fromkeys(replacements, 0)
for index, item in enumerate(l):
if item in replacements:
l[index] = replacements[item]
counts[item] += 1
print("Replacement counts:")
for k, v in counts.items():
print("{} {:>5}".format(k, v))
return ''.join(l)
There are better ways to do these things but I'll try to change your code minimally so you will learn something.
The first function's issue is that when you split the sentence like "Hello." there will be two sentences in your fixStr list that the last one is an empty string; so the first index of an empty string is out of range. fix it by doing this.
def fix_capitalization(usrStr):
count = 0
fixStr = usrStr.split('.')
for sentence in fixStr:
# changed line
if sentence != "":
sentence[0].upper()
count += 1
print('Number of letters capitalized: %d' % count)
print('Edited text: %s' % fixStr)
In second snippet you are trying to write, when you pass a string to list() you get a list of characters of that string. So all you need to do is to iterate over the elements of the list and replace them and after that get string from the list.
def replace_punctuation(usrStr):
newStr = ""
s = list(usrStr)
exclamationCount = 0
semicolonCount = 0
for c in s:
if c == '!':
c = '.'
exclamationCount += 1
if c == ';':
c = ','
semicolonCount += 1
newStr = newStr + c
print(newStr)
print(semicolonCount)
print(exclamationCount)
Hope I helped!
Python has a nice build in function for this
for str in list:
new_str = str.replace('!', '.').replace(';', ',')
You can write a oneliner to get a new list
new_list = [str.replace('!', '.').replace(';', ',') for str in list]
You also could go for the split/join method
new_str = '.'.join(str.split('!'))
new_str = ','.join(str.split(';'))
To count capitalized letters you could do
result = len([cap for cap in str if str(cap).isupper()])
And to capitalize them words just use the
str.capitalize()
Hope this works out for you

Counting words starting with a character

Write a function that accepts a string and a character as input and
returns the count of all the words in the string which start with the
given character. Assume that capitalization does not matter here. You
can assume that the input string is a sentence i.e. words are
separated by spaces and consists of alphabetic characters.
This is my code:
def count_input_character (input_str, character):
input_str = input_str.lower()
character = character.lower()
count = 0
for i in range (0, len(input_str)):
if (input_str[i] == character and input_str[i - 1] == " "):
count += 1
return (count)
#Main Program
input_str = input("Enter a string: ")
character = input("Enter character whose occurances are to be found in the given input string: ")
result = count_input_character(input_str, character)
#print(result)
The only part missing here is that how to check if the first word of the sentence is stating with the user given character. consider this output:
Your answer is NOT CORRECT Your code was tested with different inputs. > For example when your function is called as shown below:
count_input_character ('the brahman the master of the universe', 't')
####### Your function returns ############# 2 The returned variable type is: type 'int'
### Correct return value should be ######## 3 The returned variable type is: type 'int'
You function misses the first t because in this line
if (input_str[i] == character and input_str[i - 1] == " "):
when i is 0, then input_str[i - 1] is input_str[-1] which Python will resolve as the last character of the string!
To fix this, you could change your condition to
if input_str[i] == character and (i == 0 or input_str[i - 1] == " "):
Or use str.split with a list comprehension. Or a regular expression like r'(?i)\b%s', with (?i) meaning "ignore case", \b is word boundary and %s a placeholder for the character..
Instead of looking for spaces, you could split input_str on whitespace, this would produce a list of words that you could then test against character. (Pseudocode below)
function F sentence, character {
l = <sentence split by whitespace>
count = 0
for word in l {
if firstchar(word) == character {
count = count + 1
}
}
return count
}
Although it doesn't fix your specific bug, for educational purposes, please note you could rewrite your function like this using list comprehension:
def count_input_character (input_str, character):
return len([x for x in input_str.lower().split() if x.startswith(character.lower())])
or even more efficiently(thanks to tobias_k)
def count_input_character (input_str, character):
sum(w.startswith(character.lower()) for w in input_str.lower().split())
def c_upper(text, char):
text = text.title() #set leading char of words to uppercase
char = char.upper() #set given char to uppercase
k = 0 #counter
for i in text:
if i.istitle() and i == char: #checking conditions for problem, where i is a char in a given string
k = k + 1
return k

Count number of occurrences of a substring in a string

How can I count the number of times a given substring is present within a string in Python?
For example:
>>> 'foo bar foo'.numberOfOccurrences('foo')
2
To get indices of the substrings, see How to find all occurrences of a substring?.
string.count(substring), like in:
>>> "abcdabcva".count("ab")
2
This is for non overlapping occurrences.
If you need to count overlapping occurrences, you'd better check the answers here, or just check my other answer below.
s = 'arunununghhjj'
sb = 'nun'
results = 0
sub_len = len(sb)
for i in range(len(s)):
if s[i:i+sub_len] == sb:
results += 1
print results
Depending what you really mean, I propose the following solutions:
You mean a list of space separated sub-strings and want to know what is the sub-string position number among all sub-strings:
s = 'sub1 sub2 sub3'
s.split().index('sub2')
>>> 1
You mean the char-position of the sub-string in the string:
s.find('sub2')
>>> 5
You mean the (non-overlapping) counts of appearance of a su-bstring:
s.count('sub2')
>>> 1
s.count('sub')
>>> 3
The best way to find overlapping sub-strings in a given string is to use a regular expression. With lookahead, it will find all the overlapping matches using the regular expression library's findall(). Here, left is the substring and right is the string to match.
>>> len(re.findall(r'(?=aa)', 'caaaab'))
3
To find overlapping occurences of a substring in a string in Python 3, this algorithm will do:
def count_substring(string,sub_string):
l=len(sub_string)
count=0
for i in range(len(string)-len(sub_string)+1):
if(string[i:i+len(sub_string)] == sub_string ):
count+=1
return count
I myself checked this algorithm and it worked.
You can count the frequency using two ways:
Using the count() in str:
a.count(b)
Or, you can use:
len(a.split(b))-1
Where a is the string and b is the substring whose frequency is to be calculated.
Scenario 1: Occurrence of a word in a sentence.
eg: str1 = "This is an example and is easy". The occurrence of the word "is". lets str2 = "is"
count = str1.count(str2)
Scenario 2 : Occurrence of pattern in a sentence.
string = "ABCDCDC"
substring = "CDC"
def count_substring(string,sub_string):
len1 = len(string)
len2 = len(sub_string)
j =0
counter = 0
while(j < len1):
if(string[j] == sub_string[0]):
if(string[j:j+len2] == sub_string):
counter += 1
j += 1
return counter
Thanks!
The current best answer involving method count doesn't really count for overlapping occurrences and doesn't care about empty sub-strings as well.
For example:
>>> a = 'caatatab'
>>> b = 'ata'
>>> print(a.count(b)) #overlapping
1
>>>print(a.count('')) #empty string
9
The first answer should be 2 not 1, if we consider the overlapping substrings.
As for the second answer it's better if an empty sub-string returns 0 as the asnwer.
The following code takes care of these things.
def num_of_patterns(astr,pattern):
astr, pattern = astr.strip(), pattern.strip()
if pattern == '': return 0
ind, count, start_flag = 0,0,0
while True:
try:
if start_flag == 0:
ind = astr.index(pattern)
start_flag = 1
else:
ind += 1 + astr[ind+1:].index(pattern)
count += 1
except:
break
return count
Now when we run it:
>>>num_of_patterns('caatatab', 'ata') #overlapping
2
>>>num_of_patterns('caatatab', '') #empty string
0
>>>num_of_patterns('abcdabcva','ab') #normal
2
The question isn't very clear, but I'll answer what you are, on the surface, asking.
A string S, which is L characters long, and where S[1] is the first character of the string and S[L] is the last character, has the following substrings:
The null string ''. There is one of these.
For every value A from 1 to L, for every value B from A to L, the string S[A]..S[B]
(inclusive). There are L + L-1 + L-2 + ... 1 of these strings, for a
total of 0.5*L*(L+1).
Note that the second item includes S[1]..S[L],
i.e. the entire original string S.
So, there are 0.5*L*(L+1) + 1 substrings within a string of length L. Render that expression in Python, and you have the number of substrings present within the string.
One way is to use re.subn. For example, to count the number of
occurrences of 'hello' in any mix of cases you can do:
import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')
How about a one-liner with a list comprehension? Technically its 93 characters long, spare me PEP-8 purism. The regex.findall answer is the most readable if its a high level piece of code. If you're building something low level and don't want dependencies, this one is pretty lean and mean. I'm giving the overlapping answer. Obviously just use count like the highest score answer if there isn't overlap.
def count_substring(string, sub_string):
return len([i for i in range(len(string)) if string[i:i+len(sub_string)] == sub_string])
If you want to count all the sub-string (including overlapped) then use this method.
import re
def count_substring(string, sub_string):
regex = '(?='+sub_string+')'
# print(regex)
return len(re.findall(regex,string))
I will keep my accepted answer as the "simple and obvious way to do it", however, it does not cover overlapping occurrences.
Finding out those can be done naively, with multiple checking of the slices - as in:
sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
which yields 3.
Or it can be done by trick use of regular expressions, as can be seen at How to use regex to find all overlapping matches - and it can also make for fine code golfing.
This is my "hand made" count for overlapping occurrences of patterns in a string which tries not to be extremely naive (at least it does not create new string objects at each interaction):
def find_matches_overlapping(text, pattern):
lpat = len(pattern) - 1
matches = []
text = array("u", text)
pattern = array("u", pattern)
indexes = {}
for i in range(len(text) - lpat):
if text[i] == pattern[0]:
indexes[i] = -1
for index, counter in list(indexes.items()):
counter += 1
if text[i] == pattern[counter]:
if counter == lpat:
matches.append(index)
del indexes[index]
else:
indexes[index] = counter
else:
del indexes[index]
return matches
def count_matches(text, pattern):
return len(find_matches_overlapping(text, pattern))
For overlapping count we can use use:
def count_substring(string, sub_string):
count=0
beg=0
while(string.find(sub_string,beg)!=-1) :
count=count+1
beg=string.find(sub_string,beg)
beg=beg+1
return count
For non-overlapping case we can use count() function:
string.count(sub_string)
Overlapping occurences:
def olpcount(string,pattern,case_sensitive=True):
if case_sensitive != True:
string = string.lower()
pattern = pattern.lower()
l = len(pattern)
ct = 0
for c in range(0,len(string)):
if string[c:c+l] == pattern:
ct += 1
return ct
test = 'my maaather lies over the oceaaan'
print test
print olpcount(test,'a')
print olpcount(test,'aa')
print olpcount(test,'aaa')
Results:
my maaather lies over the oceaaan
6
4
2
Here's a solution that works for both non-overlapping and overlapping occurrences. To clarify: an overlapping substring is one whose last character is identical to its first character.
def substr_count(st, sub):
# If a non-overlapping substring then just
# use the standard string `count` method
# to count the substring occurences
if sub[0] != sub[-1]:
return st.count(sub)
# Otherwise, create a copy of the source string,
# and starting from the index of the first occurence
# of the substring, adjust the source string to start
# from subsequent occurences of the substring and keep
# keep count of these occurences
_st = st[::]
start = _st.index(sub)
cnt = 0
while start is not None:
cnt += 1
try:
_st = _st[start + len(sub) - 1:]
start = _st.index(sub)
except (ValueError, IndexError):
return cnt
return cnt
If you're looking for a power solution that works every case this function should work:
def count_substring(string, sub_string):
ans = 0
for i in range(len(string)-(len(sub_string)-1)):
if sub_string == string[i:len(sub_string)+i]:
ans += 1
return ans
If you want to find out the count of substring inside any string; please use below code.
The code is easy to understand that's why i skipped the comments. :)
string=raw_input()
sub_string=raw_input()
start=0
answer=0
length=len(string)
index=string.find(sub_string,start,length)
while index<>-1:
start=index+1
answer=answer+1
index=string.find(sub_string,start,length)
print answer
You could use the startswith method:
def count_substring(string, sub_string):
x = 0
for i in range(len(string)):
if string[i:].startswith(sub_string):
x += 1
return x
def count_substring(string, sub_string):
inc = 0
for i in range(0, len(string)):
slice_object = slice(i,len(sub_string)+i)
count = len(string[slice_object])
if(count == len(sub_string)):
if(sub_string == string[slice_object]):
inc = inc + 1
return inc
if __name__ == '__main__':
string = input().strip()
sub_string = input().strip()
count = count_substring(string, sub_string)
print(count)
def count_substring(string, sub_string):
k=len(string)
m=len(sub_string)
i=0
l=0
count=0
while l<k:
if string[l:l+m]==sub_string:
count=count+1
l=l+1
return count
if __name__ == '__main__':
string = input().strip()
sub_string = input().strip()
count = count_substring(string, sub_string)
print(count)
2+ others have already provided this solution, and I even upvoted one of them, but mine is probably the easiest for newbies to understand.
def count_substring(string, sub_string):
slen = len(string)
sslen = len(sub_string)
range_s = slen - sslen + 1
count = 0
for i in range(range_s):
if string[i:i+sslen] == sub_string:
count += 1
return count
I'm not sure if this is something looked at already, but I thought of this as a solution for a word that is 'disposable':
for i in xrange(len(word)):
if word[:len(term)] == term:
count += 1
word = word[1:]
print count
Where word is the word you are searching in and term is the term you are looking for
string="abc"
mainstr="ncnabckjdjkabcxcxccccxcxcabc"
count=0
for i in range(0,len(mainstr)):
k=0
while(k<len(string)):
if(string[k]==mainstr[i+k]):
k+=1
else:
break
if(k==len(string)):
count+=1;
print(count)
my_string = """Strings are amongst the most popular data types in Python.
We can create the strings by enclosing characters in quotes.
Python treats single quotes the same as double quotes."""
Count = my_string.lower().strip("\n").split(" ").count("string")
Count = my_string.lower().strip("\n").split(" ").count("strings")
print("The number of occurance of word String is : " , Count)
print("The number of occurance of word Strings is : " , Count)
For a simple string with space delimitation, using Dict would be quite fast, please see the code as below
def getStringCount(mnstr:str, sbstr:str='')->int:
""" Assumes two inputs string giving the string and
substring to look for number of occurances
Returns the number of occurances of a given string
"""
x = dict()
x[sbstr] = 0
sbstr = sbstr.strip()
for st in mnstr.split(' '):
if st not in [sbstr]:
continue
try:
x[st]+=1
except KeyError:
x[st] = 1
return x[sbstr]
s = 'foo bar foo test one two three foo bar'
getStringCount(s,'foo')
Below logic will work for all string & special characters
def cnt_substr(inp_str, sub_str):
inp_join_str = ''.join(inp_str.split())
sub_join_str = ''.join(sub_str.split())
return inp_join_str.count(sub_join_str)
print(cnt_substr("the sky is $blue and not greenthe sky is $blue and not green", "the sky"))
Here's the solution in Python 3 and case insensitive:
s = 'foo bar foo'.upper()
sb = 'foo'.upper()
results = 0
sub_len = len(sb)
for i in range(len(s)):
if s[i:i+sub_len] == sb:
results += 1
print(results)
j = 0
while i < len(string):
sub_string_out = string[i:len(sub_string)+j]
if sub_string == sub_string_out:
count += 1
i += 1
j += 1
return count
#counting occurence of a substring in another string (overlapping/non overlapping)
s = input('enter the main string: ')# e.g. 'bobazcbobobegbobobgbobobhaklpbobawanbobobobob'
p=input('enter the substring: ')# e.g. 'bob'
counter=0
c=0
for i in range(len(s)-len(p)+1):
for j in range(len(p)):
if s[i+j]==p[j]:
if c<len(p):
c=c+1
if c==len(p):
counter+=1
c=0
break
continue
else:
break
print('number of occurences of the substring in the main string is: ',counter)

Categories

Resources