Print all the "a" of a string on python - python

I'm trying to print all the "a" or other characters from an input string. I'm trying it with the .find() function but just print one position of the characters. How do I print all the positions where is an specific character like "a"

You can use find with while loop
a = "aabababaa"
k = 0
while True:
k = a.find("a", k) # This is saying to start from where you left
if k == -1:
break
k += 1
print(k)

This is also possible with much less amount of code if you don't care where you want to start.
a = "aabababaa"
for i, c in enumerate(a): # i = Index, c = Character. Using the Enumerate()
if ("a" in c):
print(i)

Some first-get-all-matches-and-then-print versions:
With a list comprehension:
s = "aslkbasaaa"
CHAR = "a"
pos = [i for i, char in enumerate(s) if char == CHAR]
print(*pos, sep='\n')
or with itertools and composition of functions
from itertools import compress
s = "aslkbasaaa"
CHAR = "a"
pos = compress(range(len(s)), map(CHAR.__eq__, s))
print(*pos, sep='\n')

Related

Find the difference between two strings of uneven length in python

a = 'abcdfjghij'
b = 'abcdfjghi'
Output : j
def diff(a, b):
string=''
for val in a:
if val not in b:
string=val
return string
a = 'abcdfjghij'
b = 'abcdfjghi'
print(diff(a,b))
This code returns an empty string.
Any solution for this?
collections.Counter from the standard library can be used to model multi-sets, so it keeps track of repeated elements. It's a subclass of dict which is performant and extends its functionality for counting purposes. To find differences between two strings you can mimic a symmetric difference between sets.
from collections import Counter
a = 'abcdfjghij'
b = 'abcdfjghi'
ca = Counter(a)
cb = Counter(b)
diff = (cb-ca)+(ca-cb) # symmetric difference
print(diff)
#Counter({'j': 1})
Its hard to know exactly what you want based on your question. Like should
'abc'
'efg'
return 'abc' or 'efg' or is there always just going to be one character added?
Here is a solution that accounts for multiple characters being different but still might not give your exact output.
def diff(a, b):
string = ''
if(len(a) >= len(b)):
longString = a
shortString = b
else:
longString = b
shortString = a
for i in range(len(longString)):
if(i >= len(shortString) or longString[i] != shortString[i]):
string += longString[i]
return string
a = 'abcdfjghij'
b = 'abcdfjghi'
print(diff(a,b))
if one string just has one character added and i could be anywhere in the string you could change
string += longString[i]
to
string = longString[i]
In your example, there are 2 differences between the 2 strings :
The letter g and j.
I tested your code and it returns g because all the other letters from are in b:
a = 'abcdfjghij'
b = 'abcdfjhi'
def diff(a, b):
string=''
for val in a:
if val not in b:
string=val
return string
print(diff(a,b))
updated
But you have j twice in a. So the first time it sees j it looks at b and sees a j, all good. For the second j it looks again and still sees a j, all good.
Are you wanting to check if each letter is the same as the other letter in the same sequence, then you should try this:
a = 'abcdfjghij'
b = 'abcdfjghi'
def diff(a, b):
if len(a)>len(b):
smallest_len = len(b)
for index, value in enumerate(a[:smallest_len]):
if a[index] != b[index]:
print(f'a value {a[index]} at index {index} does not match b value {b[index]}')
if len(a) == len(b):
pass
else:
print(f'Extra Values in A Are {a[smallest_len:]}')
else:
smallest_len = len(a)
for index, value in enumerate(b[:smallest_len]):
if a[index] != b[index]:
print(f'a value {a[index]} at index {index} does not match b value {b[index]}')
if len(a) == len(b):
pass
else:
print(f'Extra Values in B Are {b[smallest_len:]}')
diff(a, b)
if I understand correctyl your question is:
"given 2 strings of different length, how can I find the characters
that are different between them?"
So judging by your example, this implies you want either the characters that are only present in 1 of the strings and not on the other, or characters that might be repeated and which count is different in between the two strings.
Here's a simple solution (maybe not the most efficient one), but one that's short and does not require any extra packages:
**UPDATED: **
a = 'abcdfjghij'
b = 'abcdfjghi'
dict_a = dict( (char, a.count(char)) for char in a)
dict_b = dict( (char, b.count(char)) for char in b)
idx_longest = [dict_a, dict_b].index(max([dict_a, dict_b], key = len))
results = [ k for (k,v) in [dict_a, dict_b][idx_longest].items() if k not in [dict_a, dict_b][1-idx_longest].keys() or v!=[dict_a, dict_b][1-idx_longest][k] ]
print(results)
> ['j']
or you can try with other pair of strings such as
a = 'abcaa'
b = 'aaa'
print(results)
> ['b', 'c']
as 'a' is in both string an equal number of times.

How to find the longest repeated adjacent values in a string and put parentheses around them

I am trying to iterate through a string and mark () around the longest repeated adjacent values.
Example:
"344556(7777)5412"
max_run = "0"
J = "34455677775412"
for x in range(len(J)-1):
if J[x] == J[x+1]
if J[x:x+2] > max_run:
print( "(", end = "")
max_run = J[x:x+2]
print( ")", end = "")
The method groupby from package itertools of the standard library sequentially group terms, then take the maximum.
import itertools as it
ref_string = "34455677775412"
max_squence = ''.join(max((list(j) for _, j in it.groupby(ref_string)), key=len))
print(ref_string.replace(max_squence, f'({max_squence})'))
Another implementation of the body of the program (credits to Kelly Bundy): first join each group to a string and then filter by longest string
max_squence = max((''.join(j) for _, j in it.groupby(ref_string)), key=len)
Love itertools, but as there is already a (nice) solution withgroupby, here is one with a classical loop:
J = "34455677775412"
run = []
prev = None
for pos, char in enumerate(J):
if char == prev:
run[-1][0] += 1
else:
run.append([1, pos])
prev = char
print(run)
a,b = max(run, key=lambda x: x[0])
J[:b]+'('+J[b:b+a]+')'+J[b+a:]
output: '344556(7777)5412'
In case you can't use any standard library methods like groupby, here's a plain python implementation that does the same thing:
i = 0
max_start, max_end = 0, 0
J = "34455677775412"
# find the longest repeating sequence
while i < len(J):
j = i
while j < len(J) and J[j] == J[i]:
j += 1
max_start, max_end = max([(max_start, max_end), (i, j)], key=lambda e: e[1] - e[0])
i = j
print(max_start, max_end, J[max_start:max_end])
J = J[:max_start] + "(" + J[max_start:max_end] + ")" + J[max_end:] # insert the parentheses
print(J)
You could also use Python regex library re to achieve a similar solution to #cards's one
import re
J = "34455677775412"
pattern = r'(.)\1+'
longest_sequence = max([match.group() for match in re.finditer(pattern, J)])
print(J.replace(longest_sequence, f'({longest_sequence})'))

Creating a function that translates number to letter

I have written this function which is supposed to go through a user-provided string like 1-3-5, and output a corresponding series of letters, where A is assigned to 1, B is assigned to 2, C is assigned to 3, etc. So in the case of 1-3-5 the output would be ACE. For 2-3-4, it should print BCD. For ?-3-4 or --3-4 it should still print BCD. Here is the code I have written so far:
def number_to_letter(encoded):
result = ""
start = 0
for char in range(len(encoded)):
if encoded[char] == '-':
i = encoded.index("-")
sub_str = encoded[start:i]
if not sub_str.isdigit():
result += ""
else:
letter = chr(64 + int(sub_str))
if 0 < int(sub_str) < 27:
result += letter
else:
result += ""
start += len(sub_str) + 1
return result
print(num_to_let('4-3-25'))
My output is D, when it should be DCY. I am trying to do this without using any lists or using the split function, just by finding the - character in the sub-string and converting the numbers before it into a letter. What can I do?
You can try doing something like this:
def number_to_letter(encoded):
result = ""
buffer = ""
for ch in encoded:
if ch == '-':
if buffer and 0 < int(buffer) < 27:
result += chr(64 + int(buffer))
buffer = ""
elif ch.isdigit():
buffer += ch
else:
if buffer and 0 < int(buffer) < 27:
result += chr(64 + int(buffer))
return result
print(number_to_letter('1-3-5'))
output:
ACE
Explanation:
we loop for each character and add it to some buffer. when we encounter - (delimiter) we try to parse the buffer and reset it. And we do the same parsing at the end one more time and return the result.
The way the validation works is that, whenever we populate the buffer we check for number validity (using .isdigit()) and when we parse the buffer we check for the range constraints.
import string
alphabet = list(string.ascii_lowercase)
combination = "1-2-3"
def seperate(s, sep='-'):
return [s[:s.index(sep)]] + seperate(s[s.index(sep)+1:]) if sep in s else [s]
combination = seperate(combination)
print("".join([alphabet[int(i)-1] for i in combination]))
the approach of this code is to find the first '-' and then store where it is so next time we can look for the first '-' after the last one
when the comments in my code talk about a cycle means going through the loop (While looping:) once
def number_to_letter(encoded):
letterString = ""
startSubStr = 0
endSubStr = 0
looping = True
while looping:
if endSubStr > (len(encoded)-4):# if we're at the last number we don't look for '-'. we go to the end of the str and end the loop
endSubStr = len(encoded)
looping = False
else:
endSubStr = encoded.index('-', startSubStr) #find the first '-' after the '-' found in the last cycle
number = int(encoded[startSubStr:endSubStr]) #get the number between the '-' found in the last cycle through this loop and the '-' found in this one
if number < 27:
letter = chr(64 + int(number))
letterString += letter
startSubStr = endSubStr + 1 #set the start of the substring to the end so the index function doesn't find the '-' found in this cycle again
return letterString
print(number_to_letter("23-1-1-2")) #>>> WAAB
result:
WAAB
I see you don't want to use split, how about filter? ;)
import itertools
s = '1-2-3'
values = [''.join(e) for e in filter(
lambda l: l != ['-'],
[list(g) for k, g in itertools.groupby(
[*s], lambda s: s.isnumeric()
)
]
)
]
That will essentially do what .split('-') does on s. Also list(s) will behave the same as [*s] if you wanna use that instead.
Now you can just use ord and chr to construct the string you require-
start_pivot = ord('A') - 1
res = ''.join([chr(int(i) + start_pivot) for i in values])
Output
>>> s = '2-3-4'
>>> values = [''.join(e) for e in filter(
...: lambda l: l != ['-'],
...: [list(g) for k, g in itertools.groupby(
...: [*s], lambda s: s.isnumeric()
...: )
...: ]
...: )
...: ]
>>> start_pivot = ord('A') - 1
>>> res = ''.join([chr(int(i) + start_pivot) for i in values])
>>> res
'BCD'
No lists, no dicts. What about RegExp?
import re
def get_letter(n):
if int(n) in range(1,27): return chr(int(n)+64)
def number_to_letter(s):
return re.sub(r'\d+', lambda x: get_letter(x.group()), s).replace('-','')
print(number_to_letter('1-2-26')) # Output: ABZ
No lists, okay. But what about dicts?
def abc(nums):
d = {'-':'','1':'A','2':'B','3':'C','4':'D','5':'E','6':'F','7':'G','8':'H','9':'I','0':'J'}
res = ''
for n in nums: res += d[n]
return res
print(abc('1-2-3-9-0')) # Output: ABCIJ
Here is a corrected version:
def abc(nums):
d = {'-':'','1':'A','2':'B','3':'C','4':'D','5':'E','6':'F','7':'G','8':'H','9':'I','0':'J'}
res = ''
for n in nums:
if n in d:
res += d[n]
return res
print(abc('?-2-3-9-0')) # Output: BCIJ

Loop to find space with python

c = "ab cd ef gf"
n = []
for x in c:
if x == " ":
d = c.find(x)
n.append(d)
print(n)
I want this code to give me something like this. [2,5,8]
But instead it is giving me this. [2,2,2]
Please help me find the mistake. Thank you.
find() will find the first instance, so it always finds the space at index 2. You could keep track of the index as you go with enumerate() so you don't need find():
c = "ab cd ef gf"
n = []
for i, x in enumerate(c):
if x == " ":
n.append(i)
print(n)
Alternatively as a list comprehension:
[i for i, x in enumerate(c) if x == " "]
One way to do it would be:
space_idxs = []
for idx, char in enumerate(s):
if char == ' ':
space_idxs.append(idx)
That's because find(pattern) function returns the first entry of the pattern. Let me supplement your code with required function find_all(string, pattern)
def find_all(string, pattern):
start = 0
indexes = []
for char in string:
start = string.find(pattern, start)
if start == -1:
return indexes
indexes.append(start)
start += len(pattern)
c = "ab cd ef gf"
n = []
n = find_all(c, " ")
print(n)
try
c="ab cd ef gh"
x=" "
print([t for t, k in enumerate(c) if k==x])
it will return [2,5,8]
in your code you are searching for the index value of x in c, three times:
in the for loop you are taking all the characters in your string one by one,
the if loop validates if it is a space
now when the character is a space it enters the if loop
the find command will look for x (space) in c
which is 2
the same is repeated three times and are appended to n
if you want it in a list:
n=([t for t, k in enumerate(c) if k==x])

Code to output the first repeated character in given string?

I'm trying to find the first repeated character in my string and output that character using python. When checking my code, I can see I'm not index the last character of my code.
What am I doing wrong?
letters = 'acbdc'
for a in range (0,len(letters)-1):
#print(letters[a])
for b in range(0, len(letters)-1):
#print(letters[b])
if (letters[a]==letters[b]) and (a!=b):
print(b)
b=b+1
a=a+1
You can do this in an easier way:
letters = 'acbdc'
found_dict = {}
for i in letters:
if i in found_dict:
print(i)
break
else:
found_dict[i]= 1
Output:
c
Here's a solution with sets, it should be slightly faster than using dicts.
letters = 'acbdc'
seen = set()
for letter in letters:
if letter in seen:
print(letter)
break
else:
seen.add(letter)
Here is a solution that would stop iteration as soon as it finds a dup
>>> from itertools import dropwhile
>>> s=set(); next(dropwhile(lambda c: not (c in s or s.add(c)), letters))
'c'
You should use range(0, len(letters)) instead of range(0, len(letters) - 1) because range already stops counting at one less than the designated stop value. Subtracting 1 from the stop value simply makes you skip the last character of letters in this case.
Please read the documentation of range:
https://docs.python.org/3/library/stdtypes.html#range
There were a few issues with your code...
1.Remove -1 from len(letters)
2.Move back one indent and do b = b + 1 even if you don't go into the if statement
3.Indent and do a = a + 1 in the first for loop.
See below of how to fix your code...
letters = 'acbdc'
for a in range(0, len(letters)):
# print(letters[a])
for b in range(0, len(letters)):
# print(letters[b])
if (letters[a] == letters[b]) and (a != b):
print(b)
b = b + 1
a = a + 1
Nice one-liner generator:
l = 'acbdc'
next(e for e in l if l.count(e)>1)
Or following the rules in the comments to fit the "abba" case:
l = 'acbdc'
next(e for c,e in enumerate(l) if l[:c+1].count(e)>1)
If complexity is not an issue then this will work fine.
letters = 'acbdc'
found = False
for i in range(0, len(letters)-1):
for j in range(i+1, len(letters)):
if (letters[i] == letters[j]):
print (letters[j])
found = True
break
if (found):
break
The below code prints the first repeated character in a string. I used the functionality of the list to solve this problem.
def findChar(inputString):
list = []
for c in inputString:
if c in list:
return c
else:
list.append(c)
return 'None'
print (findChar('gotgogle'))
Working fine as well. It gives the result as 'g'.
def first_repeated_char(str1):
for index,c in enumerate(str1):
if str1[:index+1].count(c) > 1:
return c
return "None"
print(first_repeated_char("abcdabcd"))
str_24 = input("Enter the string:")
for i in range(0,len(str_24)):
first_repeated_count = str_24.count(str_24[i])
if(first_repeated_count > 1):
break
print("First repeated char is:{} and character is
{}".format(first_repeated_count,str_24[i]))

Categories