Changing all values of string to a certain value - python

input = ["AB0","A","BBBB"]
output = ["000","0","0000"]
Is there a function like .replace("", "") which could take in any input and give a string of zeros with the same number of characters?

There is no such built-in function, but you can easily write a list comprehension for that:
>>> input = ["AB0","A","BBBB"]
>>>
>>> ["0" * len(item) for item in input]
['000', '0', '0000']

Another way to do this (mostly for fun):
>>> input = ["AB0", "A", "BBBB"]
>>> zeros = ''.zfill
>>> [zeros(len(s)) for s in input]
['000', '0', '0000']
Note that this only works for filling with 0. If you want to fill with different characters then this method won't work.
You could use ljsut or rjust to fill with different characters...
>>> input = ["AB0", "A", "BBBB"]
>>> pad = ''.ljust
>>> [pad(len(s), '1') for s in input]
['111', '1', '1111']
However, most of these are really just clever ways to do it. They aren't faster:
>>> timeit.timeit("[pad(len(s), '1') for s in input]", 'from __main__ import pad, input')
1.3355789184570312
>>> timeit.timeit("['1' * len(s) for s in input]", 'from __main__ import pad, input')
0.8812301158905029
>>> zeros = ''.zfill
>>> timeit.timeit("[zeros(len(s)) for s in input]", 'from __main__ import zeros, input')
1.110482931137085
though, depending on your particular preferences/background, you might find one way clearer to understand than another (and that's worth something)...
FWIW, my first instinct is to use the multiplication method as proposed in
Selcuk's answer so that's probably what I find most easy to read and understandable...

This will work:
input = ["AB0","A","BBBB"]
output = ["0"*len(x) for x in input]
or the same:
input = ["AB0","A","BBBB"]
output = []
for x in input:
output.append("0"*len(x))

You can use python 're' module, like following:
import re
input = ["AB0","A","BBBB"]
output = []
for value in input:
str = re.sub(".","0",value)
output.append(str)
print output

map(lambda x:"0"*len(x),["AB0","A","BBB"])

Related

use .format() in a string in two steps

I have a string in which I want to replace some variables, but in different steps, something like:
my_string = 'text_with_{var_1}_to_variables_{var_2}'
my_string.format(var_1='10')
### make process 1
my_string.format(var_2='22')
But when I try to replace the first variable I get an Error:
KeyError: 'var_2'
How can I accomplish this?
Edit:
I want to create a new list:
name = 'Luis'
ids = ['12344','553454','dadada']
def create_list(name,ids):
my_string = 'text_with_{var_1}_to_variables_{var_2}'.replace('{var_1}',name)
return [my_string.replace('{var_2}',_id) for _id in ids ]
this is the desired output:
['text_with_Luis_to_variables_12344',
'text_with_Luis_to_variables_553454',
'text_with_Luis_to_variables_dadada']
But using .format instead of .replace.
In simple words, you can not replace few arguments with format {var_1}, var_2 in string(not all) using format. Even though I am not sure why you want to only replace partial string, but there are few approaches that you may follow as a workaround:
Approach 1: Replacing the variable you want to replace at second step by {{}} instead of {}. For example: Replace {var_2} by {{var_2}}
>>> my_string = 'text_with_{var_1}_to_variables_{{var_2}}'
>>> my_string = my_string.format(var_1='VAR_1')
>>> my_string
'text_with_VAR_1_to_variables_{var_2}'
>>> my_string = my_string.format(var_2='VAR_2')
>>> my_string
'text_with_VAR_1_to_variables_VAR_2'
Approach 2: Replace once using format and another using %.
>>> my_string = 'text_with_{var_1}_to_variables_%(var_2)s'
# Replace first variable
>>> my_string = my_string.format(var_1='VAR_1')
>>> my_string
'text_with_VAR_1_to_variables_%(var_2)s'
# Replace second variable
>>> my_string = my_string % {'var_2': 'VAR_2'}
>>> my_string
'text_with_VAR_1_to_variables_VAR_2'
Approach 3: Adding the args to a dict and unpack it once required.
>>> my_string = 'text_with_{var_1}_to_variables_{var_2}'
>>> my_args = {}
# Assign value of `var_1`
>>> my_args['var_1'] = 'VAR_1'
# Assign value of `var_2`
>>> my_args['var_2'] = 'VAR_2'
>>> my_string.format(**my_args)
'text_with_VAR_1_to_variables_VAR_2'
Use the one which satisfies your requirement. :)
Do you have to use format? If not, can you just use string.replace? like
my_string = 'text_with_#var_1#_to_variables_#var2#'
my_string = my_string.replace("#var_1#", '10')
###
my_string = my_string.replace("#var2#", '22')
following seems to work now.
s = 'a {} {{}}'.format('b')
print(s) # prints a b {}
print(s.format('c')) # prints a b c

Convert an Array, converted to a String, back to an Array

I recently found an interesting behaviour in python due to a bug in my code.
Here's a simplified version of what happened:
a=[[1,2],[2,3],[3,4]]
print(str(a))
console:
"[[1,2],[2,3],[3,4]]"
Now I wondered if I could convert the String back to an Array.Is there a good way of converting a String, representing an Array with mixed datatypes( "[1,'Hello',['test','3'],True,2.532]") including integers,strings,booleans,floats and arrays back to an Array?
There's always everybody's old favourite ast.literal_eval
>>> import ast
>>> x = "[1,'Hello',['test','3'],True,2.532]"
>>> y = ast.literal_eval(x)
>>> y
[1, 'Hello', ['test', '3'], True, 2.532]
>>> z = str(y)
>>> z
"[1, 'Hello', ['test', '3'], True, 2.532]"
ast.literal_eval is better. Just to mention, this is also a way.
a=[[1,2],[2,3],[3,4]]
string_list = str(a)
original_list = eval(string_list)
print original_list == a
# True

Python error: could not convert string to float

I have some Python code that pulls strings out of a text file:
[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854, ....]
Python code:
v = string[string.index('['):].split(',')
for elem in v:
new_list.append(float(elem))
This gives an error:
ValueError: could not convert string to float: [2.974717463860223e-06
Why can't [2.974717463860223e-06 be converted to a float?
You've still got the [ in front of your "float" which prevents parsing.
Why not use a proper module for that? For example:
>>> a = "[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]"
>>> import json
>>> b = json.loads(a)
>>> b
[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]
or
>>> import ast
>>> b = ast.literal_eval(a)
>>> b
[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]
You may do the following to convert your string that you read from your file to a list of float
>>> instr="[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]"
>>> [float(e) for e in instr.strip("[] \n").split(",")]
[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]
The reason your code is failing is, you are not stripping of the '[' from the string.
You are capturing the first bracket, change string.index("[") to string.index("[") + 1
This will give you a list of floats without the need for extra imports etc.
s = '[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]'
s = s[1:-1]
float_list = [float(n) for n in s.split(',')]
[2.467188005806714e-05, 0.18664554919828535, 0.5026880460053854]
v = string[string.index('[') + 1:].split(',')
index() return index of given character, so that '[' is included in sequence returned by [:].

Python: Nested Loop

Consider this:
>>> a = [("one","two"), ("bad","good")]
>>> for i in a:
... for x in i:
... print x
...
one
two
bad
good
How can I write this code, but using a syntax like:
for i in a:
print [x for x in i]
Obviously, This does not work, it prints:
['one', 'two']
['bad', 'good']
I want the same output. Can it be done?
List comprehensions and generators are only designed to be used as expressions, while printing is a statement. While you can effect what you're trying to do by doing
from __future__ import print_function
for x in a:
[print(each) for each in x]
doing so is amazingly unpythonic, and results in the generation of a list that you don't actually need. The best thing you could do would simply be to write the nested for loops in your original example.
Given your example you could do something like this:
a = [("one","two"), ("bad","good")]
for x in sum(map(list, a), []):
print x
This can, however, become quite slow once the list gets big.
The better way to do it would be like Tim Pietzcker suggested:
from itertools import chain
for x in chain(*a):
print x
Using the star notation, *a, allows you to have n tuples in your list.
>>> a = [("one","two"), ("bad","good")]
>>> print "\n".join(j for i in a for j in i)
one
two
bad
good
>>> for i in a:
... print "\n".join(i)
...
one
two
bad
good
import itertools
for item in itertools.chain(("one","two"), ("bad","good")):
print item
will produce the desired output with just one for loop.
The print function really is superior, but here is a much more pythonic suggestion inspired by Benjamin Pollack's answer:
from __future__ import print_function
for x in a:
print(*x, sep="\n")
Simply use * to unpack the list x as arguments to the function, and use newline separators.
You'll need to define your own print method (or import __future__.print_function)
def pp(x): print x
for i in a:
_ = [pp(x) for x in i]
Note the _ is used to indicate that the returned list is to be ignored.
This code is straightforward and simpler than other solutions here:
for i in a:
print '\n'.join([x for x in i])
Not the best, but:
for i in a:
some_function([x for x in i])
def some_function(args):
for o in args:
print o

How do I do what strtok() does in C, in Python?

I am learning Python and trying to figure out an efficient way to tokenize a string of numbers separated by commas into a list. Well formed cases work as I expect, but less well formed cases not so much.
If I have this:
A = '1,2,3,4'
B = [int(x) for x in A.split(',')]
B results in [1, 2, 3, 4]
which is what I expect, but if the string is something more like
A = '1,,2,3,4,'
if I'm using the same list comprehension expression for B as above, I get an exception. I think I understand why (because some of the "x" string values are not integers), but I'm thinking that there would be a way to parse this still quite elegantly such that tokenization of the string a works a bit more directly like strtok(A,",\n\t") would have done when called iteratively in C.
To be clear what I am asking; I am looking for an elegant/efficient/typical way in Python to have all of the following example cases of strings:
A='1,,2,3,\n,4,\n'
A='1,2,3,4'
A=',1,2,3,4,\t\n'
A='\n\t,1,2,3,,4\n'
return with the same list of:
B=[1,2,3,4]
via some sort of compact expression.
How about this:
A = '1, 2,,3,4 '
B = [int(x) for x in A.split(',') if x.strip()]
x.strip() trims whitespace from the string, which will make it empty if the string is all whitespace. An empty string is "false" in a boolean context, so it's filtered by the if part of the list comprehension.
Generally, I try to avoid regular expressions, but if you want to split on a bunch of different things, they work. Try this:
import re
result = [int(x) for x in filter(None, re.split('[,\n,\t]', A))]
Mmm, functional goodness (with a bit of generator expression thrown in):
a = "1,2,,3,4,"
print map(int, filter(None, (i.strip() for i in a.split(','))))
For full functional joy:
import string
a = "1,2,,3,4,"
print map(int, filter(None, map(string.strip, a.split(','))))
For the sake of completeness, I will answer this seven year old question:
The C program that uses strtok:
int main()
{
char myLine[]="This is;a-line,with pieces";
char *p;
for(p=strtok(myLine, " ;-,"); p != NULL; p=strtok(NULL, " ;-,"))
{
printf("piece=%s\n", p);
}
}
can be accomplished in python with re.split as:
import re
myLine="This is;a-line,with pieces"
for p in re.split("[ ;\-,]",myLine):
print("piece="+p)
This will work, and never raise an exception, if all the numbers are ints. The isdigit() call is false if there's a decimal point in the string.
>>> nums = ['1,,2,3,\n,4\n', '1,2,3,4', ',1,2,3,4,\t\n', '\n\t,1,2,3,,4\n']
>>> for n in nums:
... [ int(i.strip()) for i in n if i.strip() and i.strip().isdigit() ]
...
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
How about this?
>>> a = "1,2,,3,4,"
>>> map(int,filter(None,a.split(",")))
[1, 2, 3, 4]
filter will remove all false values (i.e. empty strings), which are then mapped to int.
EDIT: Just tested this against the above posted versions, and it seems to be significantly faster, 15% or so compared to the strip() one and more than twice as fast as the isdigit() one
Why accept inferior substitutes that cannot segfault your interpreter? With ctypes you can just call the real thing! :-)
# strtok in Python
from ctypes import c_char_p, cdll
try: libc = cdll.LoadLibrary('libc.so.6')
except WindowsError:
libc = cdll.LoadLibrary('msvcrt.dll')
libc.strtok.restype = c_char_p
dat = c_char_p("1,,2,3,4")
sep = c_char_p(",\n\t")
result = [libc.strtok(dat, sep)] + list(iter(lambda: libc.strtok(None, sep), None))
print(result)
Why not just wrap in a try except block which catches anything not an integer?
I was desperately in need of strtok equivalent in Python. So I developed a simple one by my own
def strtok(val,delim):
token_list=[]
token_list.append(val)
for key in delim:
nList=[]
for token in token_list:
subTokens = [ x for x in token.split(key) if x.strip()]
nList= nList + subTokens
token_list = nList
return token_list
I'd guess regular expressions are the way to go: http://docs.python.org/library/re.html

Categories