Sachihiro
Sachihiro

Reputation: 1793

How can I create a square list of integers in python?

I'm trying to create a square matrix, given an integer input.

For example:

# for n=3
m = [[1, 2, 3], [4, 5, 6],[7, 8, 9]] 

my attempt:

m = list(list(range(1*i,(n+1)*i,i)) for i in range(1,n+1))
print(m)

prints this result:

[[1, 2, 3], [2, 4, 6], [3, 6, 9]]

The array must be square and consist of sequential integers.

Upvotes: 4

Views: 1654

Answers (4)

Frayal
Frayal

Reputation: 2161

i rather use numpy (IT IS NOT A LIST so i know it's not the required OP, however it can still be interesting)

def func(n):
    l = np.asarray([i for i in range(1,n**2+1)])
    return l.reshape(n,n)

func(3)
>>> array([[1, 2, 3],
          [4, 5, 6],
          [7, 8, 9]])

take also in consideration the time to compute:

def func(n):
   t = time.time()
   np.arange(1, n**2 + 1).reshape((n, n))
   t1 = time.time()-t
   t = time.time()
   np.asarray([i for i in range(1,n**2+1)]).reshape(n,n)
   t2 = time.time()-t
   t = time.time()
   [list(range(1+n*i, 1+n*(i+1))) for i in range(n)]
   t3 = time.time()-t
   t = time.time()
   itr = itertools.count(1)  # start counting at 1
   matrix = [[next(itr) for _ in range(n)] for _ in range(n)]
   t4 = time.time()-t
   return [t1,t2,t3,t4]

plt.plot([re[0] for re in res],'r',label = 'numpy')
plt.plot([re[1] for re in res],'b',label = 'asarray')
plt.plot([re[2] for re in res],'m',label = 'list')
plt.plot([re[3] for re in res],'g',label = 'itertool')
plt.legend()
plt.savefig('plt1.png')

will give the following graph for 200 points: enter image description here

for large matrix, go straight for the numpy solution of @jpp

Upvotes: 1

gustavovelascoh
gustavovelascoh

Reputation: 1228

You can use comprehensive lists. For a zero-filled matrix:

mat = [[0 for i in range(N)] for i in range(N)]

For a matrix with consecutive elements (zero-based):

mat = [[(N*j + i) for i in range(N)] for j in range(N)]

For a matrix with consecutive elements (one-based):

mat = [[(N*j + i +1) for i in range(N)] for j in range(N)]

And for a square print you can use:

>>> print(*mat,sep="\n")
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

Upvotes: 0

Aran-Fey
Aran-Fey

Reputation: 43326

You can use itertools.count to create an iterator that yields ascending numbers, and then advance that iterator in a nested list comprehension using the next function:

import itertools

n = 3

itr = itertools.count(1)  # start counting at 1
matrix = [[next(itr) for _ in range(n)] for _ in range(n)]
# result: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Upvotes: 1

jpp
jpp

Reputation: 164843

Here's one way:

n = 3
m = [list(range(1+n*i, 1+n*(i+1))) for i in range(n)]

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

The main misunderstanding appears to be in spotting the pattern. For example, the first value in each column can be computed via 1 + 3 * i, where i iterates over 0, 1, 2. For the end argument of range, you just need to add n to the formula, and we can use the identity:

n*i + n = n*(i+1)

As an aside, if you are happy to use a 3rd party library, this is trivial with NumPy:

import numpy as np

n = 3
A = np.arange(1, n**2 + 1).reshape((n, n))

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

Upvotes: 1

Related Questions