Python - Right and Left Shift characters in String
In string manipulation tasks, especially in algorithmic challenges or encoding/decoding scenarios, we sometimes need to rotate (or shift) characters in a string either to the left or right by a certain number of positions.
For example, let's take a string s = "geeks" and we need to perform a left and right shift of k=2 places:
s = "geeks"
left shift = "eeksge"
right shift = "ksgee"
This article explores different ways to perform such shifts in Python using different methods, let's explore them with examples:
Using String Multiplication and Slicing
This method combines slicing with string multiplication to handle shifts efficiently in a single step. It works by dividing the string at the specified index and rearranging the parts.
s = "geeksforgeeks"
k = 3
l = s[k:] + s[:k]
r = s[-k:] + s[:-k]
print("Left Shift:", l)
print("Right Shift:", r)
Output
Left Shift: ksforgeeksgee Right Shift: eksgeeksforge
Explanation:
- s[k:] gets all characters from index k to the end and s[:k] gets the first k characters.
- s[k:] + s[:k] moves the first k characters to the end (Left Shift).
- s[-k:] + s[:-k] moves the last k characters to the front (Right Shift).
Using % Operator and Slicing
Modulo operator (%) ensures the shift value remains within the bounds of the string length. This avoids unnecessary operations when the shift value exceeds the string length.
s = "geeksforgeeks"
k = 17
n = len(s)
k %= n
l = s[k:] + s[:k]
r = s[-k:] + s[:-k]
print("Left Shift:", l)
print("Right Shift:", r)
Output
Left Shift: sforgeeksgeek Right Shift: eeksgeeksforg
Explanation:
- k %= n reduces unnecessary full rotations. Shifting a 13-character string by 17 is the same as shifting by 4 (since 17 % 13 = 4).
- Slicing is then used to perform the shifts.
Using collections.deque
Deque (double-ended queue) from the collections module is designed for efficient rotations and manipulations. This method uses the built-in rotate function of deque for shifting characters.
from collections import deque
s = "geeksforgeeks"
k = 3
d = deque(s)
d.rotate(-k)
l = ''.join(d)
d.rotate(2 * k)
r = ''.join(d)
print("Left Shift:", l)
print("Right Shift:", r)
Output
Left Shift: ksforgeeksgee Right Shift: eksgeeksforge
Explanation:
- Positive values for rotate perform right shifts, while negative values perform left shifts.
- rotate(-k) rotates left.
- rotate(2 * k) returns to original, then rotates right by k.
- The result is obtained by converting the rotated deque back into a string.
Using List Comprehension with join()
This approach uses list comprehension to calculate the shifted indices and reconstructs the string using the join() function. It provides a flexible way to perform shifts..
s = "geeksforgeeks"
k = 3
n = len(s)
k %= n
l = ''.join([s[(i + k) % n] for i in range(n)])
r = ''.join([s[(i - k) % n] for i in range(n)])
print("Left Shift:", l)
print("Right Shift:", r)
Output
Left Shift: ksforgeeksgee Right Shift: eksgeeksforge
Explanation:
- (i + k) % n computes the new index after shifting left.
- (i - k) % n computes the new index after shifting right.
- join() converts the list back to a string.
Using Itertools and islice
Cycle creates an infinitely repeating iterable from the original string. This allows us to extract the desired shifted sequence using slicing.
from itertools import cycle, islice
s = "geeksforgeeks"
k = 3
n = len(s)
k %= n
l = ''.join(islice(cycle(s), k, k + n))
r = ''.join(islice(cycle(s), n - k, 2 * n - k))
print("Left Shift:", l)
print("Right Shift:", r)
Output
Left Shift: ksforgeeksgee Right Shift: eksgeeksforge
Explanation:
- cycle(s) creates an infinite repeating iterator.
- islice(..., k, k + n) extracts a slice after skipping k characters (left shift).
- islice(..., n - k, 2 * n - k) extracts slice for right shift.
Also read: String slicing, collections.deque, list comprehension, itertools.cycle, islice.