3

I have a two-dimensional python array that looks like this:

A = [[186,192,133],[12],[122,193,154],[166,188,199],[133,44,23,56,78,96,100]]

Now how do I make a new array that looks like this?

B = [[186,12,122,166,133],[192, 193,188,44],[133,154,199,23],[56],[78],[96],[100]]

I basically want to convert the column of A into rows of B.

3 Answers 3

1

Solution

from itertools import izip_longest # in Python 3 zip_longest

list([x for x in y if x is not None] for y in izip_longest(*A))

result:

[[186, 12, 122, 166, 133],
 [192, 193, 188, 44],
 [133, 154, 199, 23],
 [56],
 [78],
 [96],
 [100]]

Explanation

izip_longest gives you an iterator:

>>> from itertools import izip_longest
>>> izip_longest([1, 2, 3], [4, 5])
<itertools.izip_longest at 0x103331890>

Convert it into a list to see what it does:

>>> list(izip_longest([1, 2, 3], [4, 5]))
[(1, 4), (2, 5), (3, None)]

It takes one element from each list and puts them pairwise into a tuple. Furthermore, it fills missing values with None ( or another value you supply).

The * allows to give a function an unspecified number of arguments. For example, we can put our two lists inside another list and use * and it still works the same:

>>> list(izip_longest(*[[1, 2, 3], [4, 5]]))
[(1, 4), (2, 5), (3, None)]

This is not limited to two arguments. An example with three.

Single arguments:

>>> list(izip_longest([1, 2, 3], [4, 5], [6]))
[(1, 4, 6), (2, 5, None), (3, None, None)]

All arguments in one list with *:

>>> list(izip_longest(*[[1, 2, 3], [4, 5], [6]]))
[(1, 4, 6), (2, 5, None), (3, None, None)]

You don't want the None values. Filter them out with a list comprehension:

>>> [x for x in y if x is not None] 

For your A, you get this:

>>> list(izip_longest(*A))
[(186, 12, 122, 166, 133),
 (192, None, 193, 188, 44),
 (133, None, 154, 199, 23),
 (None, None, None, None, 56),
 (None, None, None, None, 78),
 (None, None, None, None, 96),
 (None, None, None, None, 100)]

Now, y runs through all entries in this list such as (186, 12, 122, 166, 133). While x runs through each individual number in y such as 186. The outer [] creates a list. So instead of the tuple (186, 12, 122, 166, 133) we get a list [186, 12, 122, 166, 133]. Finally, the if x is not None filters out the None values.

Sign up to request clarification or add additional context in comments.

2 Comments

I am very new to python. I tried looking at its documentation, but I still can't understand Do you mind explaining why you put *A in izip_longest() ?
Added some background info.
1

Another method transposing using map and filter:

A = [[186, 192, 133], [12], [122, 193, 154], [166, 188, 199], [133, 44, 23, 56, 78, 96, 100]]


print([list(filter(None,sub)) for sub in map(None,*A)])
[[186, 12, 122, 166, 133], [192, 193, 188, 44], [133, 154, 199, 23], [56], [78], [96], [100]]

If 0 is a potential you will need to specifically check for None's:

print([list(filter(lambda x: x is not None, sub)) for sub in map(None,*A)])

Or map with a regular list comp as per Mikes answer:

 [[x for x in sub if x is not None] for sub in map(None,*A)]

1 Comment

Is None a function? I am wondering how this map(None,*A) is working? Isn't it like map(function, iterable, ...)? I thought map() is like lapply() in R?
0
    def rotate(A):
        B = []
        added = True
        while added:
            added = False
            col = []
            for row in A:
                try:
                    col.append(row.pop(0))
                except IndexError:
                    continue
                added = True
            col and B.append(col)
        return B

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.