Rotating strings in Python - python

I was trying to make the string HELLO to OHELL in Python. But couldn't get any way to rotate it without working with loops. How to code for it in just 1-2 lines so that I could get the desired pattern?

Here is one way:
def rotate(strg, n):
return strg[n:] + strg[:n]
rotate('HELLO', -1) # 'OHELL'
Alternatively, collections.deque ("double-ended queue") is optimised for queue-related operations. It has a dedicated rotate() method:
from collections import deque
items = deque('HELLO')
items.rotate(1)
''.join(items) # 'OHELL'

You can slice and add strings:
>>> s = 'HELLO'
>>> s[-1] + s[:-1]
'OHELL'
This gives you the last character:
>>> s[-1]
'O'
and this everything but the last:
>>> s[:-1]
'HELL'
Finally, add them with +.

Here is what I use to rotate strings in Python3:
To rotate left by n:
def leftShift(text,n):
return text[n:] + text[:n]
To rotate right by n:
def rightShift(text,n):
return text[-n:] + text[:-n]

Here is a simple way of looking at it...
s = 'HELLO'
for r in range(5):
print(s[r:] + s[:r])
HELLO
ELLOH
LLOHE
LOHEL
OHELL

I would agree with Mike Müller's answer:
s = 'HELLO'
s = s[-1] + s[:-1]
I would like to share another way of looking at s[:-1]
s[0:-1]
This means that it is starting from the start and including everything except for s[-1].
I hope this helped.

Related

Python best way to remove char from string by index [duplicate]

This question already has answers here:
Remove char at specific index - python
(8 answers)
Closed 2 months ago.
I'm removing an char from string like this:
S = "abcd"
Index=1 #index of string to remove
ListS = list(S)
ListS.pop(Index)
S = "".join(ListS)
print S
#"acd"
I'm sure that this is not the best way to do it.
EDIT
I didn't mentioned that I need to manipulate a string size with length ~ 10^7.
So it's important to care about efficiency.
Can someone help me. Which pythonic way to do it?
You can bypass all the list operations with slicing:
S = S[:1] + S[2:]
or more generally
S = S[:Index] + S[Index + 1:]
Many answers to your question (including ones like this) can be found here: How to delete a character from a string using python?. However, that question is nominally about deleting by value, not by index.
Slicing is the best and easiest approach I can think of, here are some other alternatives:
>>> s = 'abcd'
>>> def remove(s, indx):
return ''.join(x for x in s if s.index(x) != indx)
>>> remove(s, 1)
'acd'
>>>
>>>
>>> def remove(s, indx):
return ''.join(filter(lambda x: s.index(x) != 1, s))
>>> remove(s, 1)
'acd'
Remember that indexing is zero-based.
You can replace the Index character with "".
str = "ab1cd1ef"
Index = 3
print(str.replace(str[Index],"",1))
def missing_char(str, n):
n = abs(n)
front = str[:n] # up to but not including n
back = str[n+1:] # n+1 through end of string
return front + back
S = "abcd"
Index=1 #index of string to remove
S = S.replace(S[Index], "")
print(S)
I hope it helps!

Fast and pythonic way to find out if a string is a palindrome

[Edit: as someone pointed out I have used improperly the palindrom concept, now I have edited with the correct functions. I have done also some optimizations in the first and third example, in which the for statement goes until it reach half of the string]
I have coded three different versions for a method which checks if a string is a palindrome. The method are implemented as extensions for the class "str"
The methods also convert the string to lowercase, and delete all the punctual and spaces. Which one is the better (faster, pythonic)?
Here are the methods:
1) This one is the first solution that I thought of:
def palindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
n = len(lowerself)
for i in range(n//2):
if lowerself[i] != lowerself[n-(i+1)]:
return False
return True
I think that this one is the more faster because there aren't transformations or reversing of the string, and the for statement breaks at the first different element, but I don't think it's an elegant and pythonic way to do so
2) In the second version I do a transformation with the solution founded here on stackoverflow (using advanced slicing string[::-1])
# more compact
def pythonicPalindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
lowerReversed = lowerself[::-1]
if lowerself == lowerReversed:
return True
else:
return False
But I think that the slicing and the comparision between the strings make this solution slower.
3) The thirds solution that I thought of, use an iterator:
# with iterator
def iteratorPalindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
iteratorReverse = reversed(lowerself)
for char in lowerself[0:len(lowerself)//2]:
if next(iteratorReverse) != char:
return False
return True
which I think is way more elegant of the first solution, and more efficient of the second solution
So, I decided to just timeit, and find which one was the fastest. Note that the final function is a cleaner version of your own pythonicPalindrome. It is defined as follows:
def palindrome(s, o):
return re.sub("[ ,.;:?!]", "", s.lower()) == re.sub("[ ,.;:?!]", "", o.lower())[::-1]
Methodology
I ran 10 distinct tests per function. In each test run, the function was called 10000 times, with arguments self="aabccccccbaa", other="aabccccccbaa". The results can be found below.
palindrom iteratorPalindrome pythonicPalindrome palindrome
1 0.131656638 0.108762937 0.071676536 0.072031984
2 0.140950052 0.109713793 0.073781851 0.071860462
3 0.126966087 0.109586756 0.072349792 0.073776719
4 0.125113136 0.108729573 0.094633969 0.071474645
5 0.130878159 0.108602964 0.075770395 0.072455015
6 0.133569472 0.110276694 0.072811747 0.071764222
7 0.128642812 0.111065438 0.072170571 0.072285204
8 0.124896702 0.110218949 0.071898959 0.071841214
9 0.123841905 0.109278358 0.077430437 0.071747112
10 0.124083576 0.108184210 0.080211147 0.077391086
AVG 0.129059854 0.109441967 0.076273540 0.072662766
STDDEV 0.005387429 0.000901370 0.007030835 0.001781309
It would appear that the cleaner version of your pythonicPalindrome is marginally faster, but both functions clearly outclass the alternatives.
It seems that you want to know the execution time of your blocks of code and compare them.
You can use the timeit module.
Here's a quick way:
import timeit
start = timeit.default_timer()
#Your code here
stop = timeit.default_timer()
print stop - start
Read more:
Option 1
Option 2
You could also time this one-liner that does not use re, but itertools instead:
def isPalindrom(self):
return all(i==j for i, j in itertools.zip_longest((i.lower() for i in self if i not in " ,.;:?!"), (j.lower() for j in self[::-1] if j not in " ,.;:?!")))
Or, explained in more details:
def isPalindrom(self):
#using generators to not use memory
stripped_self = (i.lower() for i in self if i not in " ,.;:?!")
reversed_stripped_self = (j.lower() for j in self[::-1] if j not in " ,.;:?!")
return all(self_char==reversed_char for self_char, reversed_char in itertools.zip_longest(stripped_self, reversed_stripped_self))
Recall that filter works on strings:
>>> st="One string, with punc. That also needs lowercase!"
>>> filter(lambda c: c not in " ,.;:?!", st.lower())
'onestringwithpuncthatalsoneedslowercase'
So your test can be a one liner that is obvious in function:
>>> str
'!esacrewol sdeen osla tahT .cnup htiw ,gnirts enO'
>>> filter(lambda c: c not in " ,.;:?!", st.lower())==filter(lambda c: c not in " ,.;:?!", str.lower()[::-1])
True
Or, if you are going to use a regex, just reverse the result with the idiomatic str[::-1]:
>>> "123"[::-1]
'321'
>>> re.sub(r'[ ,.;:?!]', '', st.lower())==re.sub(r'[ ,.;:?!]', '', str.lower())[::-1]
True
The fastest may be to use string.tranlate to delete the characters:
>>> import string
>>> string.translate(st, None, " ,.;:?!")
'OnestringwithpuncThatalsoneedslowercase'
>>> string.translate(st, None, " ,.;:?!")==string.translate(str, None, " ,.;:?!")[::-1]
True
When we pass a word it checks if it can be reversed,If it can be reversed it prints "This is a Palindrome". or "This is NOT a Palindrome"
def reverse(word):
x = ''
for i in range(len(word)):
x += word[len(word)-1-i]
return x
word = input('give me a word:\n')
x = reverse(word)
if x == word:
print('This is a Palindrome')
else:
print('This is NOT a Palindrome')
Why not using a more pythonic way!
def palindrome_checker(string):
string = string.lower()
return string == string[::-1] # returns a boolean

How to make this simple string function "pythonic"

Coming from the C/C++ world and being a Python newb, I wrote this simple string function that takes an input string (guaranteed to be ASCII) and returns the last four characters. If there’s less than four characters, I want to fill the leading positions with the letter ‘A'. (this was not an exercise, but a valuable part of another complex function)
There are dozens of methods of doing this, from brute force, to simple, to elegant. My approach below, while functional, didn’t seem "Pythonic".
NOTE: I’m presently using Python 2.6 — and performance is NOT an issue. The input strings are short (2-8 characters), and I call this function only a few thousand times.
def copyFourTrailingChars(src_str):
four_char_array = bytearray("AAAA")
xfrPos = 4
for x in src_str[::-1]:
xfrPos -= 1
four_char_array[xfrPos] = x
if xfrPos == 0:
break
return str(four_char_array)
input_str = "7654321"
print("The output of {0} is {1}".format(input_str, copyFourTrailingChars(input_str)))
input_str = "21"
print("The output of {0} is {1}".format(input_str, copyFourTrailingChars(input_str)))
The output is:
The output of 7654321 is 4321
The output of 21 is AA21
Suggestions from Pythoneers?
I would use simple slicing and then str.rjust() to right justify the result using A as fillchar . Example -
def copy_four(s):
return s[-4:].rjust(4,'A')
Demo -
>>> copy_four('21')
'AA21'
>>> copy_four('1233423')
'3423'
You can simple adding four sentinel 'A' character before the original string, then take the ending four characters:
def copy_four(s):
return ('AAAA'+s)[-4:]
That's simple enough!
How about something with string formatting?
def copy_four(s):
return '{}{}{}{}'.format(*('A'*(4-len(s[-4:])) + s[-4:]))
Result:
>>> copy_four('abcde')
'bcde'
>>> copy_four('abc')
'Aabc'
Here's a nicer, more canonical option:
def copy_four(s):
return '{:A>4}'.format(s[-4:])
Result:
>>> copy_four('abcde')
'bcde'
>>> copy_four('abc')
'Aabc'
You could use slicing to get the last 4 characters, then string repetition (* operator) and concatenation (+ operator) as below:
def trailing_four(s):
s = s[-4:]
s = 'A' * (4 - len(s)) + s
return s
You can try this
def copy_four_trailing_chars(input_string)
list_a = ['A','A','A','A']
str1 = input_string[:-4]
if len(str1) < 4:
str1 = "%s%s" % (''.join(list_a[:4-len(str1)]), str1)
return str1

Python - making a function that would add "-" between letters

I'm trying to make a function, f(x), that would add a "-" between each letter:
For example:
f("James")
should output as:
J-a-m-e-s-
I would love it if you could use simple python functions as I am new to programming. Thanks in advance. Also, please use the "for" function because it is what I'm trying to learn.
Edit:
yes, I do want the "-" after the "s".
Can I try like this:
>>> def f(n):
... return '-'.join(n)
...
>>> f('james')
'j-a-m-e-s'
>>>
Not really sure if you require the last 'hyphen'.
Edit:
Even if you want suffixed '-', then can do like
def f(n):
return '-'.join(n) + '-'
As being learner, it is important to understand for your that "better to concat more than two strings in python" would be using str.join(iterable), whereas + operator is fine to append one string with another.
Please read following posts to explore further:
Any reason not to use + to concatenate two strings?
which is better to concat string in python?
How slow is Python's string concatenation vs. str.join?
Also, please use the "for" function because it is what I'm trying to learn
>>> def f(s):
m = s[0]
for i in s[1:]:
m += '-' + i
return m
>>> f("James")
'J-a-m-e-s'
m = s[0] character at the index 0 is assigned to the variable m
for i in s[1:]: iterate from the second character and
m += '-' + i append - + char to the variable m
Finally return the value of variable m
If you want - at the last then you could do like this.
>>> def f(s):
m = ""
for i in s:
m += i + '-'
return m
>>> f("James")
'J-a-m-e-s-'
text_list = [c+"-" for c in text]
text_strung = "".join(text_list)
As a function, takes a string as input.
def dashify(input):
output = ""
for ch in input:
output = output + ch + "-"
return output
Given you asked for a solution that uses for and a final -, simply iterate over the message and add the character and '-' to an intermediate list, then join it up. This avoids the use of string concatenations:
>>> def f(message)
l = []
for c in message:
l.append(c)
l.append('-')
return "".join(l)
>>> print(f('James'))
J-a-m-e-s-
I'm sorry, but I just have to take Alexander Ravikovich's answer a step further:
f = lambda text: "".join([c+"-" for c in text])
print(f('James')) # J-a-m-e-s-
It is never too early to learn about list comprehension.
"".join(a_list) is self-explanatory: glueing elements of a list together with a string (empty string in this example).
lambda... well that's just a way to define a function in a line. Think
square = lambda x: x**2
square(2) # returns 4
square(3) # returns 9
Python is fun, it's not {enter-a-boring-programming-language-here}.

How to downcase the first character of a string?

There is a function to capitalize a string, I would like to be able to change the first character of a string to be sure it will be lowercase.
How can I do that in Python?
One-liner which handles empty strings and None:
func = lambda s: s[:1].lower() + s[1:] if s else ''
>>> func(None)
>>> ''
>>> func('')
>>> ''
>>> func('MARTINEAU')
>>> 'mARTINEAU'
s = "Bobby tables"
s = s[0].lower() + s[1:]
def first_lower(s):
if len(s) == 0:
return s
else:
return s[0].lower() + s[1:]
print first_lower("HELLO") # Prints "hELLO"
print first_lower("") # Doesn't crash :-)
Interestingly, none of these answers does exactly the opposite of capitalize(). For example, capitalize('abC') returns Abc rather than AbC. If you want the opposite of capitalize(), you need something like:
def uncapitalize(s):
if len(s) > 0:
s = s[0].lower() + s[1:].upper()
return s
Simplest way:
>>> mystring = 'ABCDE'
>>> mystring[0].lower() + mystring[1:]
'aBCDE'
>>>
Update
See this answer (by #RichieHindle) for a more foolproof solution, including handling empty strings. That answer doesn't handle None though, so here is my take:
>>> def first_lower(s):
if not s: # Added to handle case where s == None
return
else:
return s[0].lower() + s[1:]
>>> first_lower(None)
>>> first_lower("HELLO")
'hELLO'
>>> first_lower("")
>>>
No need to handle special cases (and I think the symmetry is more Pythonic):
def uncapitalize(s):
return s[:1].lower() + s[1:].upper()
I'd write it this way:
def first_lower(s):
if s == "":
return s
return s[0].lower() + s[1:]
This has the (relative) merit that it will throw an error if you inadvertently pass it something that isn't a string, like None or an empty list.
This duplicate post lead me here.
If you've a list of strings like the one shown below
l = ['SentMessage', 'DeliverySucceeded', 'DeliveryFailed']
Then, to convert the first letter of all items in the list, you can use
l = [x[0].lower() + x[1:] for x in l]
Output
['sentMessage', 'deliverySucceeded', 'deliveryFailed']
pip install pydash first.
import pydash # pip install pydash
assert pydash.lower_first("WriteLine") == "writeLine"
https://github.com/dgilland/pydash
https://pydash.readthedocs.io/en/latest/
https://pypi.org/project/pydash/

Categories

Resources