The most straightforward way to build it is like this:
list_of_lists = []
for row in range(rows):
inner_list = []
for col in range(cols):
inner_list.append(None)
list_of_lists.append(inner_list)
or with a list comprehension:
list_of_lists = [[None for col in range(cols)] for row in range(rows)]
The two ways are equivalent.
Answer from Reblochon Masque on Stack Overflowpython - How to define a two-dimensional array? - Stack Overflow
How to initialize a two-dimensional array (list of lists, if not using NumPy) in Python? - Stack Overflow
Python arrays without numpy!
Python 2D list performance, without numpy - Stack Overflow
The most straightforward way to build it is like this:
list_of_lists = []
for row in range(rows):
inner_list = []
for col in range(cols):
inner_list.append(None)
list_of_lists.append(inner_list)
or with a list comprehension:
list_of_lists = [[None for col in range(cols)] for row in range(rows)]
The two ways are equivalent.
To create myList initially filled with None, you can do this:
N = 3
myList = [[None] * N for i in range(N)]
print(myList)
Which gives:
[[None, None, None], [None, None, None], [None, None, None]
Then if you want to update each cell, just loop over the rows and columns, where row is the index of the row in the matrix and col is the index of the column in the matrix. Then you can update each my_List[row][col] cell accordingly:
for row in range(N):
for col in range(N):
myList[row][col] = row + col
print(myList)
Which Outputs:
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
You're technically trying to index an uninitialized array. You have to first initialize the outer list with lists before adding items; Python calls this "list comprehension".
# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5
Matrix = [[0 for x in range(w)] for y in range(h)]
#You can now add items to the list:
Matrix[0][0] = 1
Matrix[6][0] = 3 # error! range...
Matrix[0][6] = 3 # valid
Note that the matrix is "y" address major, in other words, the "y index" comes before the "x index".
print Matrix[0][0] # prints 1
x, y = 0, 6
print Matrix[x][y] # prints 3; be careful with indexing!
Although you can name them as you wish, I look at it this way to avoid some confusion that could arise with the indexing, if you use "x" for both the inner and outer lists, and want a non-square Matrix.
If you really want a matrix, you might be better off using numpy. Matrix operations in numpy most often use an array type with two dimensions. There are many ways to create a new array; one of the most useful is the zeros function, which takes a shape parameter and returns an array of the given shape, with the values initialized to zero:
>>> import numpy
>>> numpy.zeros((5, 5))
array([[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
Here are some other ways to create 2-d arrays and matrices (with output removed for compactness):
numpy.arange(25).reshape((5, 5)) # create a 1-d range and reshape
numpy.array(range(25)).reshape((5, 5)) # pass a Python range and reshape
numpy.array([5] * 25).reshape((5, 5)) # pass a Python list and reshape
numpy.empty((5, 5)) # allocate, but don't initialize
numpy.ones((5, 5)) # initialize with ones
numpy provides a matrix type as well, but it is no longer recommended for any use, and may be removed from numpy in the future.
To initialize a two-dimensional list in Python, use
t = [ [0]*3 for i in range(3)]
But don't use [[v]*n]*n, it is a trap!
>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
A pattern that often came up in Python was
bar = []
for item in some_iterable:
bar.append(SOME EXPRESSION)
which helped motivate the introduction of list comprehensions, which convert that snippet to
bar = [SOME_EXPRESSION for item in some_iterable]
which is shorter and sometimes clearer. Usually, you get in the habit of recognizing these and often replacing loops with comprehensions.
Your code follows this pattern twice
twod_list = [] \
for i in range (0, 10): \
new = [] \ can be replaced } this too
for j in range (0, 10): } with a list /
new.append(foo) / comprehension /
twod_list.append(new) /
So obviously, I would like to avoid the first solution, especially since this will be running for sizes up to 100k. However, I also do not want to use too many dependencies.
You must choose which of these is more important to you. Numpy has better performance precisely because it doesn't use the builtin Python types and uses its own types that are optimized for numerical work. If your data are going to be numeric and you're going to have 100k rows/columns, you will see a gigantic performance increase with numpy. If you want to avoid the numpy dependency, you will have to live with reduced performance. (Obviously you can always write your own Python libraries or C extensions to optimize for your particular use case, but these will then be dependencies like any other.)
Personally I would recommend you just use numpy. It is so widely used that anyone who is considering using a library that deals with 100k multidimensional arrays probably already has numpy installed.
I tried a couple of alternatives;
Edit: The original eArray was faulty, it created references to the same list...
Edit2: Added array.array as suggested by Sebastian.
import time
import numpy as np
import array
t1 = 0
def starttimer():
global t1
t1 = time.clock()
def stoptimer(s):
t2 = time.clock()
print 'elapsed time for "{}": {:.3f} seconds'.format(s, t2-t1)
def cArray(size):
c = [[0. for i in range(size)] for j in range(size)]
return c
def dArray(size):
d = [[0. for i in xrange(size)] for j in xrange(size)]
return d
def eArray2(size):
return [[0.]*size for j in xrange(size)]
def fArray(size):
return np.zeros((size,size))
def gArray(size):
return [array.array('d', [0])*size for j in xrange(size)]
sz = 5000
starttimer()
cArray(sz)
stoptimer('cArray')
starttimer()
dArray(sz)
stoptimer('dArray')
starttimer()
fArray(sz)
stoptimer('fArray')
starttimer()
gArray(sz)
stoptimer('gArray')
The results (cpython 2.7.3 on FreeBSD amd64, if anyone cares):
> python tmp/test.py
elapsed time for "cArray": 2.312 seconds
elapsed time for "dArray": 1.945 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.695 seconds
> python tmp/test.py
elapsed time for "cArray": 2.312 seconds
elapsed time for "dArray": 1.914 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.695 seconds
> python tmp/test.py
elapsed time for "cArray": 2.328 seconds
elapsed time for "dArray": 1.906 seconds
elapsed time for "eArray2": 0.680 seconds
elapsed time for "fArray": 0.180 seconds
elapsed time for "gArray": 0.703 seconds
I think what you're looking for is a DataFrame?
import pandas as pd
player_score = [1,0,1,1,0]
cpu_score = [0,1,0,0,1]
df = pd.DataFrame([player_score, cpu_score])
df.columns = ["G1", "G2", "G3", "G4", "G5"]
df.index = ['Player', 'CPU']
print(df)
gives
G1 G2 G3 G4 G5
Player 1 0 1 1 0
CPU 0 1 0 0 1
Numpy and pandas are powerful tools in Python programming, but trying working without them helps to learn better. They provide a diversity of useful functions and object classes, to work without which means that you may have to define your own.
To display the scoreboard that you wish, I'd recommend that you define your own scoreboard class. I'll give you an example like this:
class ScoreBoard:
def __init__(self):
self.player_score = [1,0,1,1,0]
self.cpu_score = [0,1,0,0,1]
def __str__(self):
string = '\t'
for i in range(len(self.player_score)):
string += 'G%d '%(i+1)
string = string + '\n\nPlayer\t'
for i in range(len(self.player_score)):
string += '%d '%self.player_score[i]
string = string + '\nCPU\t'
for i in range(len(self.cpu_score)):
string += '%d '%self.cpu_score[i]
return string
def record_score(self, player_score, cpu_score):
self.player_score.append(player_score)
self.cpu_score.append(cpu_score)
and if you
a = ScoreBoard()
print(a)
a.record_score(1, 0)
print(a)
, this would be shown:
G1 G2 G3 G4 G5
Player 1 0 1 1 0
CPU 0 1 0 0 1
G1 G2 G3 G4 G5 G6
Player 1 0 1 1 0 1
CPU 0 1 0 0 1 0
Obviously, more should be done to make this class work well.
1) The initial player_score and cpu_score have to be []
2) What if the scoreboard is empty? When it's empty, would you decorate the string output?
3) Is there a possibility that it's a draw, like Rock vs. Rock? If not, cpu_score can be calculated when you have player_score. In that case, one of these two is not necessary.
4) Perhaps it can become a scoreboard for more games where there are more players?
5) Perhaps you can even define your own labeled 2D arrays, like pandas.DataFrame?
If you haven't learned about Object-Oreinted-Programming in Python, you're free to ask. You can also learn more in Python Programming Tutorials.
You could use the random module and populate a nested list with a list comprehension
import random
low = 0
high = 10
cols = 10
rows = 5
[random.choices(range(low,high), k=cols) for _ in range(rows)]
[[5, 7, 1, 0, 6, 5, 9, 2, 5, 6],
[9, 2, 3, 0, 6, 7, 0, 6, 6, 3],
[2, 7, 9, 2, 4, 5, 5, 9, 9, 4],
[2, 6, 7, 8, 5, 1, 4, 4, 4, 4],
[9, 2, 8, 4, 5, 2, 0, 1, 2, 1]]
For a nested list of floats, you can map each range with float:
choices = list(map(float, range(low,high)))
[random.choices(choices , k=cols) for _ in range(rows)]
[[0.0, 3.0, 9.0, 1.0, 5.0, 3.0, 7.0, 4.0, 2.0, 4.0],
[5.0, 8.0, 7.0, 7.0, 7.0, 2.0, 9.0, 8.0, 2.0, 6.0],
[3.0, 3.0, 1.0, 9.0, 2.0, 8.0, 7.0, 2.0, 9.0, 7.0],
[7.0, 8.0, 1.0, 2.0, 0.0, 6.0, 7.0, 6.0, 0.0, 9.0],
[3.0, 3.0, 3.0, 1.0, 7.0, 8.0, 3.0, 9.0, 2.0, 8.0]]
[[random.random() for _ in range(3)] for _ in range(7)]
This generates a 2D array of size [7, 3] with random float in [0, 1) interval.
You use nested list comprehensions. The outer one builds a main list while the inner one builds lists that are used as elements of the main list.
Edit
You can then tweak it for your needs. For example:
import random
import pprint
NUM_ROWS=7
NUM_COLS=3
MAX_VAL=1000.50
MIN_VAL=-MAX_VAL
pprint.pprint([
[random.uniform(MIN_VAL, MAX_VAL) for _ in NUM_COLS]
for _ in NUM_ROWS
])
This prints a list/array/matrix of 7 lines and 3 colums with random floats in [-1000.50, 1000.50) interval:
[[561.3985362160208, -157.9871329592354, -245.7102502320838],
[-817.8786101352823, -528.9769041860632, 102.67728824479877],
[-886.6488625065194, 941.0504221837489, -458.58155555154565],
[6.69525238666165, 919.5903586746183, 66.70453038938808],
[754.3718741592056, -121.25678519054622, -577.7163532922043],
[-352.3158889341157, 254.9985130814921, -365.0937338693691],
[563.0633042715097, 833.2963094260072, -946.6729221921638]]
The resulting array can be indexed with array[line][column].
Hello!
I have 5 sets, each set contains a number of elements of variable length (eg. set 1 has 100 elements, set 2 has 150 and so on)
Is it possible to store these sets in a single structure?
For example, if I want to print the 35th elements of the 3rd set, I could call it simply by saying something like MyContainer[setN][elementN]
I was trying to use a 2D array but I can't initialize its shape, since each set has a variable number of elements.
Can anybody point me to the right direction / best practice?
Thank you
Hello,
I'm learning to code in Python and I'm stuck on a part of a question. I have googled a lot and tried to do it without success.
The user enters two matrices that are retained in the program as two-dimensional lists. The program checks whether the matrix sizes allow matrix multiplication and in that case performs the matrix multiplication. The result is saved in a new two-dimensional list.
I succeed with the part where users input the lists, but do not know how to proceed after that. Does anyone have any ideas on how to do this? I'm not allowed to use numpy on this assignment.
I would really appreciate some help.