Sub matrix of a list of lists (without numpy)

前端 未结 4 1368
误落风尘
误落风尘 2020-12-09 12:04

Suppose I have a matrix composed of a list of lists like so:

>>> LoL=[list(range(10)) for i in range(10)]
>>> LoL
[[0, 1, 2, 3, 4, 5, 6, 7,         


        
相关标签:
4条回答
  • 2020-12-09 12:44

    Do this,

    submat = [ [ mat[ i ][ j ] for j in range( index1, index2 ) ] for i in range( index3, index4 ) ]

    the submat will be the rectangular (square if index3 == index1 and index2 == index4) chunk of your original big matrix.

    0 讨论(0)
  • 2020-12-09 12:48
    In [74]: [row[2:5] for row in LoL[1:4]]
    Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
    

    You could also mimic NumPy's syntax by defining a subclass of list:

    class LoL(list):
        def __init__(self, *args):
            list.__init__(self, *args)
        def __getitem__(self, item):
            try:
                return list.__getitem__(self, item)
            except TypeError:
                rows, cols = item
                return [row[cols] for row in self[rows]]
    
    lol = LoL([list(range(10)) for i in range(10)])
    print(lol[1:4, 2:5])
    

    also yields

    [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
    

    Using the LoL subclass won't win any speed tests:

    In [85]: %timeit [row[2:5] for row in x[1:4]]
    1000000 loops, best of 3: 538 ns per loop
    In [82]: %timeit lol[1:4, 2:5]
    100000 loops, best of 3: 3.07 us per loop
    

    but speed isn't everything -- sometimes readability is more important.

    0 讨论(0)
  • 2020-12-09 12:50

    I dont know if its easier, but let me throw an idea to the table:

    from itertools import product
    r = (1+1, 4+1)
    s = (2+1, 5+1)
    array = [LoL[i][j] for i,j in product(range(*r), range(*s))]
    

    This is a flattened version of the submatrix you want.

    0 讨论(0)
  • 2020-12-09 13:03

    For one, you can use slice objects directly, which helps a bit with both the readability and performance:

    r = slice(1,4)
    s = slice(2,5)
    [LoL[i][s] for i in range(len(LoL))[r]]
    

    And if you just iterate over the list-of-lists directly, you can write that as:

    [row[s] for row in LoL[r]]
    
    0 讨论(0)
提交回复
热议问题