Single specific character removal without slicing nor strip , - python

how can i remove a single character from a string ?
Basically i have a string like :
abccbaa
I wish to remove the first and last letter. With the string.rstrip or string.lstrip methods all of the occurrences are removed and i get a string bccb. the same goes to replace.
is there a way of doing so ? i cannot import anything , i cant use slicing (except accessing single letter ) . Also I cannot use any kind of loops as well .
To get the whole picture , i need to write a recursive palindrome algorithm. My current code is:
def is_palindrome(s):
if s == '':
return True
if s[0] != s[-1]:
return False
else:
s = s.replace(s[0], '')
s = s.replace(s[-1], '')
return is_palindrome(s)
print is_palindrome("abccbaa")
as you can see it will work unless provides with a string like the one in the print line , since more than "edge" letters are stripped .

Slicing/replacing the string isn't needed and is costly because it creates strings over and over. In languages where strings are much less convenient to handle (like C), you wouldn't even have imagined to do like that.
Of course you need some kind of looping, but recursion takes care of that.
You could do it "the old way" just pass the start & end indices recursively, with a nested function to hide the start condition to the caller:
def is_palindrome(s):
def internal_method(s,start,end):
if start>=end:
return True
if s[start] != s[end]:
return False
else:
return internal_method(s,start+1,end-1)
return internal_method(s,0,len(s)-1)
recursion stops if start meets end or if checked letters don't match (with a different outcome of course)
testing a little bit seems to work :)
>>> is_palindrome("")
True
>>> is_palindrome("a")
True
>>> is_palindrome("ab")
False
>>> is_palindrome("aba")
True
>>> is_palindrome("abba")
True
>>> is_palindrome("abbc")
False

I'm taking a guess at what you are looking for here since your question wasn't all that clear but this works for taking off the first and last character of the word you provided?
Python 2.7.14 (default, Nov 12 2018, 12:56:03)
>>> string = "abccbaa"
>>> print(string[1:-1])
bccba

Related

Python - using Regex to return True if all substrings are contained within string

str = "chair table planttest"
substr = ["plant", "tab"]
x = func(substr, str)
print(x)
I want code that will return True if str contains all strings in the substr list, regardless of position. If str does not contain all the elements in substr, it should return False.
I have been trying to use re.search or re.findall but am having a very hard time understanding regex operators.
Thanks in advance!
You need to loop through all of the substrings and use the in operator to decide if they are in the string. Like this:
def hasAllSubstrings(partsArr, fullStr):
allFound = true
for part in partsArr:
if part not in fullStr:
allFound = false
return allFound
# Test
full = "chair table planttest"
parts = ["plant", "tab"]
x = hasAllSubstrings(parts, full)
print(x)
Let's see what the hasAllSubstrings function.
It creates a boolean variable that decides if all substrings have been found.
It loops through each part in the partsArr sent in to the function.
If that part is not in the full string fullStr, it sets the boolean to false.
If multiple are not found, it will still be false, and it won't change. If everything is found, it will always be true and not false.
At the end, it returns whether it found everything.
After the function definition, we test the function with your example. There is also one last thing you should take note of: your variables shouldn't collide with built-ins. You used the str variable, and I changed it to full because str is a (commonly used) function in the Python standard library.
By using that name, you effectively just disabled the str function. Make sure to avoid those names as they can easily make your programs harder to debug and more confusing. Oh, and by the way, str is useful when you need to convert a number or some other object into a string.
You can simply use the built-in function all() and the in keyword:
fullstr = "chair table planttest"
substr = ["plant", "tab"]
x = all(s in fullstr for s in substr)
In continuation to the answer of # Lakshya Raj, you can add break after allFound = false.
Because, as soon as the first item of the sub_strung is not found in str, it gives your desired output. No need to loop further.
allFound = false
break

I need help making my program more streamline, as I am sure where are many things I am missing

Testing if a string is a palindrome or not and should be O(n) runtime. We cannot use any import statements or any other helper methods can be used.
So basically my program is to receive an input which is a string that can contain anything. If something in that string is not part of the alphabet it is to ignore it, such as spaces or commas. My program currently works but seems like there should be ways that I could make my program better, by either reducing code or something that I am just unaware of.
An example would be with the string ' E.U.V, vV V,U,E' so the first thing mine does is it goes to string[0] which is just a space and shorts to recalling itself with isPalindrome(string[1]:len(string)-1) so isPalindrome('E.U.V, vV V,U,E').
def isPalindrome (string):
if len(string) <=1: # Basecase to check if the string has less than or equal to 1 element remaining in the string so that the recursion may end
return True
if string.isalpha(): # Checks if the string is all letters of the alphabet and proceeds if true
if (string[0].lower() == string[len(string)-1].lower()): # Compares the lowercase form of the first element and the last element and if they are equal the program will proceed
return isPalindrome(string[1:len(string)-1]) # Function is calling itself with the next elements in the string
else:
return False
else:
if string[0].isalpha(): # Checks if the first element in the string is part of the alphabet and proceeds if true
if string[len(string)-1].isalpha(): # Checks if the last element of the string is part of the element and proceeds if true
if (string[0].lower()== string[len(string)-1].lower()): # Both the first and last element have been confirmed as being part of the alphabet and will not be compared to each other, program proceeds if true
return isPalindrome(string[1:len(string)-1]) # Function is calling itself with the next elements in the string
else:
return False # Program return false when some elements do not equal each other
else:
return isPalindrome(string[0:len(string)-1]) # Function is calling itself with the next elements in the string
else:
return isPalindrome(string[1:len(string)]) # Function is calling itself with the next elements in the string
Well, that is a lot of code for palindrome checking.
Essentially, a palindrome is a string that equals itself if read from the end. You can check that with the slice notation on strings. Now to clean your string from everything that is not a letter, a small list comprehension will do.
def isPalindrome(text):
text = "".join([x for x in text if x.isalpha()])
return text==text[::-1]

How to repeat some operation without knowing how many times it has to be repeated? [duplicate]

What is an efficient way to check that a string s in Python consists of just one character, say 'A'? Something like all_equal(s, 'A') which would behave like this:
all_equal("AAAAA", "A") = True
all_equal("AAAAAAAAAAA", "A") = True
all_equal("AAAAAfAAAAA", "A") = False
Two seemingly inefficient ways would be to: first convert the string to a list and check each element, or second to use a regular expression. Are there more efficient ways or are these the best one can do in Python? Thanks.
This is by far the fastest, several times faster than even count(), just time it with that excellent mgilson's timing suite:
s == len(s) * s[0]
Here all the checking is done inside the Python C code which just:
allocates len(s) characters;
fills the space with the first character;
compares two strings.
The longer the string is, the greater is time bonus. However, as mgilson writes, it creates a copy of the string, so if your string length is many millions of symbols, it may become a problem.
As we can see from timing results, generally the fastest ways to solve the task do not execute any Python code for each symbol. However, the set() solution also does all the job inside C code of the Python library, but it is still slow, probably because of operating string through Python object interface.
UPD: Concerning the empty string case. What to do with it strongly depends on the task. If the task is "check if all the symbols in a string are the same", s == len(s) * s[0] is a valid answer (no symbols mean an error, and exception is ok). If the task is "check if there is exactly one unique symbol", empty string should give us False, and the answer is s and s == len(s) * s[0], or bool(s) and s == len(s) * s[0] if you prefer receiving boolean values. Finally, if we understand the task as "check if there are no different symbols", the result for empty string is True, and the answer is not s or s == len(s) * s[0].
>>> s = 'AAAAAAAAAAAAAAAAAAA'
>>> s.count(s[0]) == len(s)
True
This doesn't short circuit. A version which does short-circuit would be:
>>> all(x == s[0] for x in s)
True
However, I have a feeling that due the the optimized C implementation, the non-short circuiting version will probably perform better on some strings (depending on size, etc)
Here's a simple timeit script to test some of the other options posted:
import timeit
import re
def test_regex(s,regex=re.compile(r'^(.)\1*$')):
return bool(regex.match(s))
def test_all(s):
return all(x == s[0] for x in s)
def test_count(s):
return s.count(s[0]) == len(s)
def test_set(s):
return len(set(s)) == 1
def test_replace(s):
return not s.replace(s[0],'')
def test_translate(s):
return not s.translate(None,s[0])
def test_strmul(s):
return s == s[0]*len(s)
tests = ('test_all','test_count','test_set','test_replace','test_translate','test_strmul','test_regex')
print "WITH ALL EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="AAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("AAAAAAAAAAAAAAAAA") != True:
print globals()[test]("AAAAAAAAAAAAAAAAA")
raise AssertionError
print
print "WITH FIRST NON-EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="FAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("FAAAAAAAAAAAAAAAA") != False:
print globals()[test]("FAAAAAAAAAAAAAAAA")
raise AssertionError
On my machine (OS-X 10.5.8, core2duo, python2.7.3) with these contrived (short) strings, str.count smokes set and all, and beats str.replace by a little, but is edged out by str.translate and strmul is currently in the lead by a good margin:
WITH ALL EQUAL
test_all 5.83863711357
test_count 0.947771072388
test_set 2.01028490067
test_replace 1.24682998657
test_translate 0.941282987595
test_strmul 0.629556179047
test_regex 2.52913498878
WITH FIRST NON-EQUAL
test_all 2.41147494316
test_count 0.942595005035
test_set 2.00480484962
test_replace 0.960338115692
test_translate 0.924381017685
test_strmul 0.622269153595
test_regex 1.36632800102
The timings could be slightly (or even significantly?) different between different systems and with different strings, so that would be worth looking into with an actual string you're planning on passing.
Eventually, if you hit the best case for all enough, and your strings are long enough, you might want to consider that one. It's a better algorithm ... I would avoid the set solution though as I don't see any case where it could possibly beat out the count solution.
If memory could be an issue, you'll need to avoid str.translate, str.replace and strmul as those create a second string, but this isn't usually a concern these days.
You could convert to a set and check there is only one member:
len(set("AAAAAAAA"))
Try using the built-in function all:
all(c == 'A' for c in s)
If you need to check if all the characters in the string are same and is equal to a given character, you need to remove all duplicates and check if the final result equals the single character.
>>> set("AAAAA") == set("A")
True
In case you desire to find if there is any duplicate, just check the length
>>> len(set("AAAAA")) == 1
True
Adding another solution to this problem
>>> not "AAAAAA".translate(None,"A")
True
Interesting answers so far. Here's another:
flag = True
for c in 'AAAAAAAfAAAA':
if not c == 'A':
flag = False
break
The only advantage I can think of to mine is that it doesn't need to traverse the entire string if it finds an inconsistent character.
not len("AAAAAAAAA".replace('A', ''))

Writing string comparing function in python

Im trying to write a function that get 2 arguments (2 strings actually) and compares them (ignoring the difference in upper/lower cases). For example:
cmr_func('House', 'HouSe')
true
cmr_func('Chair123', 'CHAIr123')
true
cmr_func('Mandy123', 'Mandy1234')
False.
Well, I tried something, but it seems very stupid and bad designed function, which anyway does not work. I would like to get idea. I believe i need to use some built-in str function, but im not sure how they can help me.
I thought about using in function with some loop. But i dont know on what kind of object should i apply a loop.
def str_comp(a,b):
for i in a:
i.lower()
for i in b:
i.lower()
if a == b:
print 'true'
else:
print 'false'
Any hint or idea are welcomed. Thanks :)
You can just convert both strings to lower-case and compare those results:
def str_comp (a, b):
return a.lower() == b.lower()
The idea behind this is normalization. Basically, you want to take any input string, and normalize it in a way that all other strings that are considered equal result in the same normalized string. And then, you just need to compare the normalized strings for equality.
Other operations you might consider are stripping whitespace (using str.strip()), or even more complex operations like converting umlauts to 2-letter combinations (e.g. ä to ae).
The problem with your solution is that you seem to assume that iterating over a string will allow you to modify the characters individually. But strings are immutable, so you cannot modify an existing string without creating a new one. As such, when you iterate over a string using for i in a you get many individual, independent strings for each character which are in no way linked to the original string a. So modifying i will not affect a.
Similarly, just calling str.lower() will not modify the string either (since it’s immutable), so instead, the function will return a new string with all letters converted to lower-case.
Finally, you shouldn’t return a string “True” or “False”. Python has boolean constants True and False which should be used for that. And if you use them, you don’t need to do the following either:
if condition:
return True
else:
return False
Since condition already is interpreted as a boolean, you can just return the condition directly to get the same result:
return condition
First you dont need to iterate the String to make all chars lowercase.
You can just:
a.lower()
b.lower()
Or you can do it all together:
def str_comp(a,b):
return a.lower() == b.lower()
Dont forget you're also returning True or False a Boolean, not returning a String (in this case the string "True" or "False")
If you want to return a String is function would different :
def str_comp(a,b):
if a.lower() == b.lower()
return "True"
return "False"
The function str.lower() actually works in a slightly different way:
This is no in-place modification. Calling a.lower() returns a copy of a with only lowercase letters and does not change a itself.
str.lower() can be called on whole strings, not just characters, so the for i in a loop won't be necessary.
Therefore you could simplify your function like following:
def str_comp(a, b):
if a.lower() == b.lower():
print 'true'
else:
print 'false'
def are_strings_equal(string_1, string_2):
return string_1.lower() == string_2.lower()

Navigating around a string in python

Pardon the incredibly trivial/noob question, at least it should be easy to answer. I've been working through the coderbyte problems and solving the easy ones in python, but have come across a wall. the problem is to return True if a string (e.g. d+==f+d++) has all alpha characters surrounded by plus signs (+) and if not return false. I'm blanking on the concept that would help navigate around these strings, I tried doing with a loop and if statement, but it failed to loop through the text entirely, and always returned false (from the first problem):
def SimpleSymbols(str):
split = list(str)
rawletters = "abcdefghijklmnopqrstuvwxyz"
letters = list(rawletters)
for i in split:
if i in letters and (((split.index(i)) - 1) == '+') and (((split.index(i)) + 1) == '+'):
return True
else:
return False
print SimpleSymbols(raw_input())
Also editing to add the problem statement: "Using the Python language, have the function SimpleSymbols(str) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter."
Any assistance would be greatly appreciated. Thank you!
Here's how I would do the first part (if I weren't using regex):
import string
LOWERCASE = set(string.ascii_lowercase)
def plus_surrounds(s):
"""Return True if `+` surrounds a single ascii lowercase letter."""
# initialize to 0 -- The first time through the loop is guaranteed not
# to find anything, but it will initialize `idx1` and `idx2` for us.
# We could actually make this more efficient by factoring out
# the first 2 `find` operations (left as an exercise).
idx2 = idx1 = 0
# if the indices are negative, we hit the end of the string.
while idx2 >= 0 and idx1 >= 0:
# if they're 2 spaces apart, check the character between them
# otherwise, keep going.
if (idx2 - idx1 == 2) and (s[idx1+1] in LOWERCASE):
return True
idx1 = s.find('+', idx2)
idx2 = s.find('+', max(idx1+1, 0))
return False
assert plus_surrounds('s+s+s')
assert plus_surrounds('+s+')
assert not plus_surrounds('+aa+')
I think that if you study this code and understand it, you should be able to get the second part without too much trouble.
More of a note than an answer, but I wanted to mention regular expressions as a solution not because it's the right one for your scenario (this looks distinctly homework-ish so I understand you're almost certainly not allowed to use regex) but just to ingrain upon you early that in Python, almost EVERYTHING is solved by import foo.
import re
def SimpleSymbols(target):
return not (re.search(r"[^a-zA-Z+=]",target) and re.search(r"(?<!\+)\w|\w(?!\+)",target))

Categories

Resources