Jonny Vu
Jonny Vu

Reputation: 1428

Elegant way to work with 2D list in python

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

Answers (4)

B. M.
B. M.

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

Mike Robins
Mike Robins

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

be_good_do_good
be_good_do_good

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

karthik reddy
karthik reddy

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

Related Questions