Python string replace - python

I have this code:
ALPHABET1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "TES"
ALPHABET2 = key + ALPHABET1
count_result = ALPHABET2.count("T")
if (count_result > 1):
ALPHABET3 = ALPHABET1.replace("T","")
ALPHABET2 = key + ALPHABET3
print(ALPHABET2)
I want to be able to put the keyword at the start of the alphabet string to create a new string without repeating the letters in the keyword. I'm having some problems doing this though. I need the keyword to work for all letters as it will be user input in my program. Any suggestions?

Two things:
You don't need to make the alphabet yourself, import string and use string.ascii_uppercase; and
You can use a for loop to work through the characters in your key.
To illustrate the latter:
for c in key:
alphabet = alphabet.replace(c, "")
Better yet, a list is mutable, so you can do:
alpha = [c for c in string.ascii_uppercase if c not in key]
alpha.extend(set(key))

its easy and clean to do this with a regex
import re
ALPHABET1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "TES"
newalphabet = key.upper() + re.sub(r'%s'%'|'.join(key.upper()), '', ALPHABET1)
or with a list comprehension like #jonrsharpe suggested

Related

How do I reverse words in a string with Python

I am trying to reverse words of a string, but having difficulty, any assistance will be appreciated:
S = " what is my name"
def reversStr(S):
for x in range(len(S)):
return S[::-1]
break
What I get now is: eman ym si tahw
However, I am trying to get: tahw is ym eman (individual words reversed)
def reverseStr(s):
return ' '.join([x[::-1] for x in s.split(' ')])
orig = "what is my name"
reverse = ""
for word in orig.split():
reverse = "{} {}".format(reverse, word[::-1])
print(reverse)
Since everyone else's covered the case where the punctuation moves, I'll cover the one where you don't want the punctuation to move.
import re
def reverse_words(sentence):
return re.sub(r'[a-zA-Z]+', lambda x : x.group()[::-1], sentence)
Breaking this down.
re is python's regex module, and re.sub is the function in that module that handles substitutions. It has three required parameters.
The first is the regex you're matching by. In this case, I'm using r'\w+'. The r denotes a raw string, [a-zA-Z] matches all letters, and + means "at least one".
The second is either a string to substitute in, or a function that takes in a re.MatchObject and outputs a string. I'm using a lambda (or nameless) function that simply outputs the matched string, reversed.
The third is the string you want to do a find in a replace in.
So "What is my name?" -> "tahW si ym eman?"
Addendum:
I considered a regex of r'\w+' initially, because better unicode support (if the right flags are given), but \w also includes numbers and underscores. Matching - might also be desired behavior: the regexes would be r'[a-zA-Z-]+' (note trailing hyphen) and r'[\w-]+' but then you'd probably want to not match double-dashes (ie --) so more regex modifications might be needed.
The built-in reversed outputs a reversed object, which you have to cast back to string, so I generally prefer the [::-1] option.
inplace refers to modifying the object without creating a copy. Yes, like many of us has already pointed out that python strings are immutable. So technically we cannot reverse a python string datatype object inplace. However, if you use a mutable datatype, say bytearray for storing the string characters, you can actually reverse it inplace
#slicing creates copy; implies not-inplace reversing
def rev(x):
return x[-1::-1]
# inplace reversing, if input is bytearray datatype
def rev_inplace(x: bytearray):
i = 0; j = len(x)-1
while i<j:
t = x[i]
x[i] = x[j]
x[j] = t
i += 1; j -= 1
return x
Input:
x = bytearray(b'some string to reverse')
rev_inplace(x)
Output:
bytearray(b'esrever ot gnirts emose')
Try splitting each word in the string into a list (see: https://docs.python.org/2/library/stdtypes.html#str.split).
Example:
>>string = "This will be split up"
>>string_list = string.split(" ")
>>string_list
>>['This', 'will', 'be', 'split', 'up']
Then iterate through the list and reverse each constituent list item (i.e. word) which you have working already.
def reverse_in_place(phrase):
res = []
phrase = phrase.split(" ")
for word in phrase:
word = word[::-1]
res.append(word)
res = " ".join(res)
return res
[thread has been closed, but IMO, not well answered]
the python string.lib doesn't include an in place str.reverse() method.
So use the built in reversed() function call to accomplish the same thing.
>>> S = " what is my name"
>>> ("").join(reversed(S))
'eman ym si tahw'
There is no obvious way of reversing a string "truly" in-place with Python. However, you can do something like:
def reverse_string_inplace(string):
w = len(string)-1
p = w
while True:
q = string[p]
string = ' ' + string + q
w -= 1
if w < 0:
break
return string[(p+1)*2:]
Hope this makes sense.
In Python, strings are immutable. This means you cannot change the string once you have created it. So in-place reverse is not possible.
There are many ways to reverse the string in python, but memory allocation is required for that reversed string.
print(' '.join(word[::-1] for word in string))
s1 = input("Enter a string with multiple words:")
print(f'Original:{s1}')
print(f'Reverse is:{s1[::-1]}')
each_word_new_list = []
s1_split = s1.split()
for i in range(0,len(s1_split)):
each_word_new_list.append(s1_split[i][::-1])
print(f'New Reverse as List:{each_word_new_list}')
each_word_new_string=' '.join(each_word_new_list)
print(f'New Reverse as String:{each_word_new_string}')
If the sentence contains multiple spaces then usage of split() function will cause trouble because you won't know then how many spaces you need to rejoin after you reverse each word in the sentence. Below snippet might help:
# Sentence having multiple spaces
given_str = "I know this country runs by mafia "
tmp = ""
tmp_list = []
for i in given_str:
if i != ' ':
tmp = tmp + i
else:
if tmp == "":
tmp_list.append(i)
else:
tmp_list.append(tmp)
tmp_list.append(i)
tmp = ""
print(tmp_list)
rev_list = []
for x in tmp_list:
rev = x[::-1]
rev_list.append(rev)
print(rev_list)
print(''.join(rev_list))
output:
def rev(a):
if a == "":
return ""
else:
z = rev(a[1:]) + a[0]
return z
Reverse string --> gnirts esreveR
def rev(k):
y = rev(k).split()
for i in range(len(y)-1,-1,-1):
print y[i],
-->esreveR gnirts

Enciphering and Deciphering by Shuffling in Python

I am writing a program that enciphers (and will eventually decipher) a given string.
The encipher function takes two arguments: the string and a seed value.
Here is what I have so far:
def random_encipher(string,seed):
random.seed(seed)
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
#shuffle alphabet
random.shuffle(alphabet)
#assign index to each letter in alphabet
for letter in alphabet:
letter = ord(letter)-97
To sum all that up, basically I'm shuffling the alphabet and assigning each letter a number value ("a" = 0, "b" = 1, . . .)
Here's what I need help with:
I need string[0] to be printed as alphabet[0] (which is the shuffled alphabet, therefore with the current seed value, alphabet[0] = "e").
But for each letter of the string, not just the zero index.
Maybe something like that?
>>> import random
>>> def random_encipher(string,seed):
random.seed(seed)
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
#shuffle alphabet
random.shuffle(alphabet)
ciphers = []
#assign index to each letter in alphabet
for letter in string:
index = ord(letter)-97
cipher = alphabet[index]
ciphers.append(cipher)
return "".join(ciphers)
>>> random_encipher("foobar", 3)
'fwwqgc'
The point in using a list, is that as strings are immutable, appending to a string requires the string to be copied which is costly. Appending to a list and merging the elements at the end is a better choice (or use a StringIO).
What you are effectively doing is creating a mapping between letters.
Luckily, python actually has an easy-to-use map object (dict):
So, to create a random mapping:
keys = string.ascii_lowercase
# this shuffles the string
values = ''.join(
random.sample(string.ascii_lowercase, len(string.ascii_lowercase))
)
mapping = dict(zip(keys, values))
And we want the reverse of this mapping for deciphering, so we use dict comprehension:
reverse_mapping = {v: k for k, v in mapping.iteritems()}
Now it's simply a matter of using the mapping on ciphering and deciphering:
def translate(s, mapping, missing=' '):
return ''.join([mapping.get(c, missing) for c in s])
And to use the translation function:
encrypted = translate("my string", mapping)
print encrypted
# verify deciphering works
decrypted = translate(encrypted, reverse_mapping)
print decrypted
The whole thing together:
#!/usr/bin/env python
import string
import random
# ... set 'seed', or factor to a function
random.seed(seed)
keys = string.ascii_lowercase
values = ''.join(
random.sample(string.ascii_lowercase, len(string.ascii_lowercase))
)
mapping = dict(zip(keys, values))
reverse_mapping = {v: k for k, v in mapping.iteritems()}
def translate(s, mapping, missing=' '):
return ''.join([mapping.get(c, missing) for c in s])
encrypted = translate("my string", mapping)
print encrypted
# verify deciphering works
decrypted = translate(encrypted, reverse_mapping)
print decrypted
Output:
up jsqlao
my string
Here's what I ended up using:
def random_encipher(s,n):
random.seed(n)
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
#shuffle alphabet
random.shuffle(alphabet)
print alphabet
#build empty list
list = []
string = ""
#build enciphered string
for letter in s:
if letter.isalpha(): #if character is a letter, print as corresponding index in shuffled alphabet
list.append(alphabet[ord(letter)-97],)
word = string.join(list)
else: #includes punctuation, spaces, etc.
list.append(letter),
word = string.join(list)
print word
random_encipher(s,n)

How to collect defined items in lists python

I have to find the signs "a..,z", "A,..,Z", "space", "." and "," in some data.
I have tried the code:
fh = codecs.open("mydata.txt", encoding = "utf-8")
text = fh.read()
fh1 = unicode(text)
dic_freq_signs = dict(Counter(fh1.split()))
All_freq_signs = dic_freq_signs.items()
List_signs = dic_freq_signs.keys()
List_freq_signs = dic_freq_signs.values()
BUT it gets me ALL signs not the ones i am looking for?
Can anyone help?
(And it has to be unicode)
check dictionary iteration ..
All_freq_signs = [ item for item in dic_freq_signs.items() if item.something == "somevalue"]
def criteria(value):
return value%2 == 0
All_freq_signs = [ item for item in dic_freq_signs.items() if criteria(item)]
Make sure you import string module, with it you can get character ranges a to z and A to Z easily
import string
A Counter(any_string) gives the count of each character in the string. By using split() the counter would return the counts of each word in the string, contradicting with your requirement. So I have assumed that you need character counts.
dic_all_chars = dict(Counter(fh1)) # this gives counts of all characters in the string
signs = string.lowercase + string.uppercase + ' .,' # these are the characters you want to check
# using dict comprehension and checking if the key is in the characters you want
dic_freq_signs = {key: value for key, value in dic_all_chars.items()
if key in signs}
dic_freq_signs would only have the signs that you want to count as keys and their counts as values.

How to remove substring from a string in python?

How can I remove the all lowercase letters before and after "Johnson" in these strings?
str1 = 'aBcdJohnsonzZz'
str2 = 'asdVJohnsonkkk'
Expected results are as below:
str1 = 'BJohnsonZ'
str2 = 'VJohnson'
You can partition the string, check it had the separator, than translate out lowercase letters, eg:
from string import ascii_lowercase as alc
str1 = 'aBcdJohnsonzZz'
p1, sep, p2 = str1.partition('Johnson')
if sep:
str1 = p1.translate(None, alc) + sep + p2.translate(None, alc)
print str1
str.partition() is your friend here:
def munge(text, match):
prefix, match, suffix = text.partition(match)
prefix = "".join(c for c in prefix if not c.islower())
suffix = "".join(c for c in suffix if not c.islower())
return prefix + match + suffix
Example use:
>>> munge("aBcdJohnsonzZz", "Johnson")
'BJohnsonZ'
>>> munge("asdVJohnsonkkk", "Johnson")
'VJohnson'
import re
def foo(input_st, keep_st):
parts = input_st.split(keep_st)
clean_parts = [re.sub("[a-z]*", "", part) for part in parts]
return keep_st.join(clean_parts)
Other methods using the partition module don't seem to take into account your trigger word being repeated. This example will work in the case you have 'aBcJohnsonDeFJohnsonHiJkL' in the event that, that particular case is of concern to you.
There are a couple of ways you could tackle this. Here's the simplest one I could think of. The idea is to tackle it in three parts. First off, you need to know the middle string. In your case 'Johnson.' Then you can remove the lowercase letters from the part before and the part after.
def removeLowercaseAround(full, middle):
stop_at = full.index(middle) #the beginning of the name
start_again = stop_at+len(middle) #the end of the name
new_str = ''; #the string we'll return at the end
for i in range(stop_at): #for each char until the middle starts
if not full[i].islower(): #if it is not a lowercase char
new_str += full[i] #add it to the end of the new string
new_str+=middle #then add the middle char
for i in range(start_again, len(full)): #do the same thing with the end
if not full[i].islower(): #if it is not a lowercase char
new_str += full[i] #add it to the string
return new_str
print removeLowercaseAround('ABcdJohnsonzZZ', 'Johnson')
Not exactly very simple or streamlined, but you could do this sort of thing (based partially on Zero Piraeus')
(edited to reflect errors)
def remove_lower(string):
return ''.join(filter(str.isupper, string))
def strip_johnson(input_str):
prefix, match, postfix = input_str.partition("Johnson")
return (
remove_lower(prefix) +
match +
remove_lower(postfix)
)

Persistent index in python string

I'm trying to get string.index() to ignore instances of a character that it has already located within a string. Here is my best attempt:
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def save_alphabet(phrase):
saved_alphabet = ""
for item in phrase:
if item in alphabet:
saved_alphabet = saved_alphabet + str(phrase.index(item))
return saved_alphabet
print save_alphabet("aAaEaaUA")
The output I'd like is "1367" but, as it only finds the first instance of item it is outputting "1361".
What's the best way to do this? The returned value should be in string format.
>>> from string import ascii_uppercase as alphabet
>>> "".join([str(i) for i, c in enumerate("aAaEaaUA") if c in alphabet])
'1367'
regex solution (do not prefer regex in this case)
>>> import re
>>> "".join([str(m.start()) for m in re.finditer(r'[A-Z]', "aAaEaaUA")])
'1367'

Categories