Reputation: 1428
I have just start with Python 2.7 for few months. I usually work with some 2D list in Python, simple task but I wonder that is there some more elegant way to do the same my job in Python 2.7?
Here is my task. I have a 2D list:
my_list = [["__cat_1", "__cat_2"],
["__cat_3", "__cat_4"]]
I want to convert the above 2D string list to 2D integer list.
expected_result = [[1, 2], [3, 4]]
As usual, I do as the following:
def convert_2D_string_list(my_list):
for a_group in my_list:
yield [int(k.replace("__cat_","")) for k in a_group]
But the above could not work when my input has 3 dimensions like:
my_second_list = [[["__cat_1", "__cat_2"], "__cat_12"],
[["__cat_3", "__cat_4"], "__cat_34"]]
If my input list is integer
, I know the elegant way to convert for transform it. For example:
def convert_2D_int_list:
my_list = [[1, 2], [3, 4]]
import numpy as np
# Assume that, I want to add 1 for each of element
# Convert to numpy array
my_list = np.asarray(my_list)
my_list += 1
# my_list = [[2, 3], [4, 5]]
return my_list
What is the best practice for my convert_2D_string_list
method?
So in case of it is not 2D list, but 3D list -> I will not afraid about the number of dimensions.
Any suggestion would be appreciated. Thank you.
Upvotes: 2
Views: 122
Reputation: 18668
Numpy array works very well with NUMbers, it's a little more tricky with strings. np.vectorize
is a work around for such situation, even no performance improvement is done. But it manages any number of dimensions, hope you will find it elegant.
a=np.array([[[['__cat_0', '__cat_1'],
['__cat_2', '__cat_3']],
[['__cat_4', '__cat_5'],
['__cat_6', '__cat_7']]],
[[['__cat_8', '__cat_9'],
['__cat_10', '__cat_11']],
[['__cat_12', '__cat_13'],
['__cat_14', '__cat_15']]]])
def f(str): return int(str[6:])
fv=np.vectorize(f)
print(fv(a))
gives :
[[[[ 0 1]
[ 2 3]]
[[ 4 5]
[ 6 7]]]
[[[ 8 9]
[10 11]]
[[12 13]
[14 15]]]]
Remark : a
is np.vectorize(lambda n : '__cat_'+str(n))(np.arange(16).reshape((2,)*4))
;)
Upvotes: 2
Reputation: 1773
Modify the values whilst recursively copying the list(s).
def visit(fn, xs):
return [visit(fn, x) if isinstance(x, list) else fn(x) for x in xs]
in this case the modification function fn
is something like:
def categorize(s):
return int(re.match(r'__cat_(\d*)', s).group(1))
testing this:
my_second_list = [[["__cat_1", "__cat_2"], "__cat_12"],
[["__cat_3", "__cat_4"], "__cat_34"]]
print visit(categorize, my_second_list)
outputs:
> [[[1, 2], 12], [[3, 4], 34]]
Upvotes: 2
Reputation: 4441
You can convert your string 2D list to int 2D list using map and list comprehensions
my_list = [["__cat_1", "__cat_2"],["__cat_3", "__cat_4"]]
my_list = [map(lambda z: int(z.split('_')[-1]), ls) for ls in my_list]
print my_list # [[1,2],[3,4]]
3d list:
my_list = [["__cat_1", "__cat_2", '__cat_3'],["__cat_1", "__cat_2", '__cat_3']]
my_list = [map(lambda z: int(z.split('_')[-1]), ls) for ls in my_list]
print my_list # [[1,2,3],[1,2,3],[1,2,3]]
Upvotes: 0
Reputation: 479
I hope this may useful for you:
def con(x):
# you can do here whatever u want
return x.split('_')[-1]
y= [con(v) for v in my_list]
Upvotes: 0