python translating strings, and changing them back using dictionary - python

I've got this code that translates a string (that starts out as a list) using a dictionary. I wanted the code to translate the string, then un-translate it back to the original.
This is the code that I've got so far:
words = ['Abra', ' ', 'cadabra', '!']
clues = {'A':'Z', 'a':'z', 'b':'y', 'c':'x'}
def converter(words, clues):
words = ''.join(words)
for item in words:
if item in clues.keys():
words = words.replace(item, clues[item])
return words
def reversal(clues):
clues = {v: k for k, v in clues.items()}
print(clues)
x = converter(words, clues)
print(x)
reversal(clues)
x = converter(words, clues)
print(x)
Only, this will print
"Zyrz xzdzyrz!"
"Zyrz xdzyrz!"
I'm not sure why it's not printing:
"Zyrz xzdzyrz!"
"Abra cadabra!"
Is there an error in my code that is causing it to act this way? I checked clues and it IS reversed properly after it goes through the function. What am I doing wrong?

Python already has the translate method on all strings, just call it!
def converter(text, clues, reverse=False):
if reverse:
clues = {v: k for k, v in clues.items()}
table = str.maketrans(clues)
return text.translate(table)
Usage:
words = ['Abra', ' ', 'cadabra', '!']
clues = {'A':'Z', 'a':'z', 'b':'y', 'c':'x'}
# join the text into a single string:
x = ''.join(words)
# convert first
x = converter(x, clues)
print(x) # -> you get `Zyrz xzdzyrz!`
#back to original
x = converter(x, clues, reverse=True)
print(x) # -> you get `Abra cadabra!`

Looks like you're trying to do a dictionary operation in place within a function. Your function needs to return the reversed version of the dictionary which you then need to pick up in your main:
# Your stuff here
def reversal(clues):
return {v: k for k, v in clues.items()}
x = converter(words, clues)
print(x)
clues_reversed = reversal(clues)
x = converter(words, clues_reversed)
print(x)

Related

Return the name of a list if it contain the needed value (Python)

am trying to get the name of a list (type list) if it contain the needed value:
def f(Value):
a = ['a','b','c']
b = ['d','e','f']
d = ['g','h','i']
c = ['j','k','l']
w = next(n for n,v in filter(lambda t: isinstance(t[1],list), locals().items()) if value in v)
return(w)
f()
well this code will return the name of the list but type string so i will be not able to use it later. thank you in advance
You got several errors in your code - if you want the list, then return it and not it's name:
def f(value): # capitalization not correct
a = ['a','b','c']
b = ['d','e','f']
d = ['g','h','i']
c = ['j','k','l']
# set w to v not n - n is the local name, v is the value
w = next(v for n,v in filter(lambda t: isinstance(t[1],list),
locals().items()) if value in v)
return w
# needs to be called with parameter
what_list = f("h")
print( what_list )
Output:
['g', 'h', 'i']
I don't see the point why using locals().items() in this minimal example, you could do
for li in [a,b,c,d]: # simply add more lists if needed, no need to inspect locals
if value in li:
return li
instead.

How to replace text between parentheses in Python?

I have a dictionary containing the following key-value pairs: d={'Alice':'x','Bob':'y','Chloe':'z'}
I want to replace the lower case variables(values) by the constants(keys) in any given string.
For example, if my string is:
A(x)B(y)C(x,z)
how do I replace the characters in order to get a resultant string of :
A(Alice)B(Bob)C(Alice,Chloe)
Should I use regular expressions?
re.sub() solution with replacement function:
import re
d = {'Alice':'x','Bob':'y','Chloe':'z'}
flipped = dict(zip(d.values(), d.keys()))
s = 'A(x)B(y)C(x,z)'
result = re.sub(r'\([^()]+\)', lambda m: '({})'.format(','.join(flipped.get(k,'')
for k in m.group().strip('()').split(','))), s)
print(result)
The output:
A(Alice)B(Bob)C(Alice,Chloe)
Extended version:
import re
def repl(m):
val = m.group().strip('()')
d = {'Alice':'x','Bob':'y','Chloe':'z'}
flipped = dict(zip(d.values(), d.keys()))
if ',' in val:
return '({})'.format(','.join(flipped.get(k,'') for k in val.split(',')))
else:
return '({})'.format(flipped.get(val,''))
s = 'A(x)B(y)C(x,z)'
result = re.sub(r'\([^()]+\)', repl, s)
print(result)
Bonus approach for particular input case A(x)B(y)C(Alice,z):
...
s = 'A(x)B(y)C(Alice,z)'
result = re.sub(r'\([^()]+\)', lambda m: '({})'.format(','.join(flipped.get(k,'') or k
for k in m.group().strip('()').split(','))), s)
print(result)
I assume you want to replace the values in a string with the respective keys of the dictionary. If my assumption is correct you can try this without using regex.
First the swap the keys and values using dictionary comprehension.
my_dict = {'Alice':'x','Bob':'y','Chloe':'z'}
my_dict = { y:x for x,y in my_dict.iteritems()}
Then using list_comprehension, you replace the values
str_ = 'A(x)B(y)C(x,z)'
output = ''.join([i if i not in my_dict.keys() else my_dict[i] for i in str_])
Hope this is what you need ;)
Code
import re
d={'Alice':'x','Bob':'y','Chloe':'z'}
keys = d.keys()
values = d.values()
s = "A(x)B(y)C(x,z)"
for i in range(0, len(d.keys())):
rx = r"" + re.escape(values[i])
s = re.sub(rx, keys[i], s)
print s
Output
A(Alice)B(Bob)C(Alice,Chloe)
Also you could use the replace method in python like this:
d={'x':'Alice','y':'Bob','z':'Chloe'}
str = "A(x)B(y)C(x,z)"
for key in d:
str = str.replace(key,d[key])
print (str)
But yeah you should swipe your dictionary values like Kishore suggested.
This is the way that I would do it:
import re
def sub_args(text, tosub):
ops = '|'.join(tosub.keys())
for argstr, _ in re.findall(r'(\(([%s]+?,?)+\))' % ops, text):
args = argstr[1:-1].split(',')
args = [tosub[a] for a in args]
subbed = '(%s)' % ','.join(map(str, args))
text = re.sub(re.escape(argstr), subbed, text)
return text
text = 'A(x)B(y)C(x,z)'
tosub = {
'x': 'Alice',
'y': 'Bob',
'z': 'Chloe'
}
print(sub_args(text, tosub))
Basically you just use the regex pattern to find all of the argument groups and substitute in the proper values--the nice thing about this approach is that you don't have to worry about subbing where you don't want to (for example, if you had a string like 'Fn(F,n)'). You can also have multi-character keys, like 'F(arg1,arg2)'.

Converting strings within a list into floats

I have a list of numerical values that are of type "string" right now. Some of the elements in this list have more than one value, e.g.:
AF=['0.056', '0.024, 0.0235', '0.724', '0.932, 0.226, 0.634']
The other thing is that some of the elements might be a .
With that being said, I've been trying to convert the elements of this list into floats (while still conserving the tuple if there's more than one value), but I keep getting the following error:
ValueError: could not convert string to float: .
I've tried a LOT of things to solve this, with the latest one being:
for x in AF:
if "," in x: #if there are multiple values for one AF
elements= x.split(",")
for k in elements: #each element of the sub-list
if k != '.':
k= map(float, k)
print(k) #check to see if there are still "."
else:
pass
But when I run that, I still get the same error. So I printed k from the above loop and sure enough, there were still . in the list, despite me stating NOT to include those in the string-to-float conversion.
This is my desired output:
AF=[0.056, [0.024, 0.0235], 0.724, [0.932, 0.226, 0.634]]
def convert(l):
new = []
for line in l:
if ',' in line:
new.append([float(j) for j in line.split(',')])
else:
try:
new.append(float(line))
except ValueError:
pass
return new
>>> convert(AF)
[0.056, [0.024, 0.0235], 0.724, [0.932, 0.226, 0.634]]
If you try this:
result = []
for item in AF:
if item != '.':
values = list(map(float, item.split(', ')))
result.append(values)
You get:
[[0.056], [0.024, 0.0235], [0.724], [0.932, 0.226, 0.634]]
You can simplify using a comprehension list:
result = [list(map(float, item.split(', ')))
for item in AF
if item != '.']
With re.findall() function (on extended input list):
import re
AF = ['0.056', '0.024, 0.0235, .', '.', '0.724', '0.932, 0.226, 0.634', '.']
result = []
for s in AF:
items = re.findall(r'\b\d+\.\d+\b', s)
if items:
result.append(float(items[0]) if len(items) == 1 else list(map(float, items)))
print(result)
The output:
[0.056, [0.024, 0.0235], 0.724, [0.932, 0.226, 0.634]]

Strings and Dictionaries in Python

I want to create a simple cipher.
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "XPMGTDHLYONZBWEARKJUFSCIQV"
def main():
while True:
plain = raw_input("text to be encoded: ")
print encode(plain)
def encode(plain):
length = len(plain)
plain = plain.upper()
for c in plain:
encoded = _______
return encoded
Input : CAT , Output : MXU
I have this template in mind but What is the best way to do this ? If I have to use dictionary, how do I use it in given set up?
A very efficient way of doing this is to make use of the .translate() method of strings:
import string
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "XPMGTDHLYONZBWEARKJUFSCIQV"
cipher = string.maketrans(alpha, key)
def encode(plaintext):
return plaintext.translate(cipher)
With your two strings:
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "XPMGTDHLYONZBWEARKJUFSCIQV"
Create a dictionary using zip():
mydict = {k:v for k, v in zip(alpha, key)} # Or dict(zip(alpha, key))
Then in your encode() function, you can just do:
def encode(plain):
return ''.join([mydict.get(i, i) for i in plain])
[mydict.get(i, i) for i in plain] Is equivalent to:
newlist = []
for i in plain:
newlist.append(mydict.get(i, i))
mydict.get(i, i) is equivalent to mydict[i], but if there is no key i, then i (the second parameter) is returned (instead of raising a KeyError)
Note that the list will return something like ['M', 'X', 'U'], so the ''.join() will print it as 'MXU'
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
key = "XPMGTDHLYONZBWEARKJUFSCIQV"
inp = 'CAT'
_d = {e[0]: e[1] for e in zip(alpha, key)}
print _d
print ''.join([_d[ele] for ele in inp if ele in _d])

editing List content in Python

I have a variable data:
data = [b'script', b'-compiler', b'123cds', b'-algo', b'timing']
I need to convert it to remove all occurrence of "b" in the list.
How can i do that?
Not sure whether it would help - but it works with your sample:
initList = [b'script', b'-compiler', b'123cds', b'-algo', b'timing']
resultList = [str(x) for x in initList ]
Or in P3:
resultList = [x.decode("utf-8") for x in initList ] # where utf-8 is encoding used
Check more on decode function.
Also you may want to take a look into the following related SO thread.
>>> a = [b'script', b'-compiler', b'123cds', b'-algo', b'timing']
>>> map(str, a)
['script', '-compiler', '123cds', '-algo', 'timing']
strin = "[b'script', b'-compiler', b'123cds', b'-algo', b'timing']"
arr = strin.strip('[]').split(', ')
res = [part.strip("b'") for part in arr]
>>> res
['script', '-compiler', '123cds', '-algo', 'timing']

Categories