1

Just when I think I'm decent at something, I find a simple thing I cannot overcome.

I need to create a symmetrical row x column matrix given a start and block for a checksum. The entries should be in sequential order.

def main(start_index, block):
    num_rows, num_cols = block, block
    matrix = []

    for r in range(num_rows):
        temp = []

        for c in range(num_cols):
            temp.append(c)

        matrix.append(temp)

    return matrix

The output here is: [[0, 1, 2], [0, 1, 2], [0, 1, 2]]

What I'm trying to obtain is: [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

And not just for a 3x3 but dynamically as well.

Note: No packages like numpy, that's not the point of this ask. Only native python.

3 Answers 3

1

You are appending c which is always a range between 0 and num_cols. You need to calculate c based on which row you are in. Something like:

def main(start_index, block):
    num_rows, num_cols = block, block
    matrix = []

    for r in range(num_rows):
        temp = []

        for c in range(0, num_cols):
            temp.append(start_index + c + (r * num_cols))

        matrix.append(temp)

    return matrix

main(0, 3)

>> [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

You could also write this as a generator from start_index to row * columns that generates your rows lazily. For example:

def main(start_index, block):
    num_rows, num_cols = block, block

    total = num_rows * num_cols

    for i in range(start_index, total + start_index, num_cols):
        yield list(range(i, num_cols + i))

list(main(10, 4))
>> [[10, 11, 12, 13], [14, 15, 16, 17], [18, 19, 20, 21], [22, 23, 24, 25]]
Sign up to request clarification or add additional context in comments.

5 Comments

Where did the 0th position in the 0th list entry go here? The 0 in [0,1,2] I manually fixed it start_index-1 But I don't quite see where we missed the iteration.
@phtaedrus not sure why I was adding one. See edit.
Thanks, @Mark_Meyer. Checked. For the generator function, wouldn't it be considered non-python to use a while instead of for loops?
@phtaedrus, I'm not sure — I think the while loop is easier to read, but you can also do it as a for loop over a range. See edit.
I like this method a lot. Now looking into pythonic generators. Much appreciated!
1

Are you overcomplicating?

In [1]: nrow, ncol, start = 3, 5, 7                                                       

In [2]: [[start+c+r*ncol for c in range(ncol)] for r in range(nrow)]                      
Out[2]: [[7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19, 20, 21]]

Should you prefer more descriptive names:

In [3]: n_rows, n_cols, n_start = 3,5,7                        

In [4]: [[n_start + col + row*n_cols for col in range(n_cols)] for row in range(n_rows)]               
Out[4]: [[7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19, 20, 21]]

Eventually, to have itertools.count you absolutely don't need to import itertools

In [10]: def count(start=0, step=1): 
    ...:     while True: 
    ...:         yield start 
    ...:         start += step 

In [11]: nr, nc, item = 3, 4, count()                                                                                                                                              

In [12]: [[next(item) for c in range(nc)] for r in range(nr)]                                                                                                                      
Out[12]: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]

In [13]: nr, nc, item = 3, 4, count(start=4, step=3)                                                                                                                               

In [14]: [[next(item) for c in range(nc)] for r in range(nr)]                                                                                                                      
Out[14]: [[4, 7, 10, 13], [16, 19, 22, 25], [28, 31, 34, 37]]

1 Comment

Hey @gboffi, I don't think so, I like the list comprehension but in this case I don't find that easily readable.
0

You can use itertools.count to create a generator for generating incrementing integers, every call to next will get the next integer

Then you can use this generator for filling in the values when you create your lists

import itertools

def get_square_matrix(size):
    counter = itertools.count(start_index)
    matrix = []
    for row in range(size):
        matrix.append([next(counter) for _ in range(size)])
    return matrix

1 Comment

Thank you! But I'm trying to use zero imports. Sorry, I 'll correct my statement but what I meant was only standard python, no imports.

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.