En Python, je veux un moyen intuitif de créer une liste en 3 dimensions.
Je veux une liste (n par n). Donc, pour n = 4, cela devrait être:
x = [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]
J'ai essayé d'utiliser:
y = [n*[n*[]]]
y = [[[]]* n for i in range(n)]
Tous deux semblent créer des copies d'une référence ... J'ai également essayé l'application naïve du constructeur de liste avec peu de succès
y = [[[]* n for i in range(n)]* n for i in range(n)]
y = [[[]* n for i in range(1)]* n for i in range(n)]
J'ai également essayé de construire le tableau de manière itérative à l'aide de boucles, sans succès. J'ai aussi essayé ceci:
y = []
for i in range(0,n):
y.append([[]*n for i in range(n)])
Y a-t-il un moyen plus facile ou plus intuitif de faire cela?
Je pense que vos versions de compréhension de liste étaient sur le point de fonctionner. Vous n'avez pas besoin de multiplier les listes (ce qui ne fonctionne de toute façon pas avec les listes vides). Voici une version de travail:
>>> y = [[[] for i in range(n)] for i in range(n)]
>>> print y
[[[], [], [], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]]
ressemble le plus simple est la suivante:
def create_empty_array_of_shape(shape):
if shape: return [create_empty_array_of_shape(shape[1:]) for i in xrange(shape[0])]
c'est un travail pour moi
j'ai trouvé ça:
Matrix = [[0 for x in xrange(5)] for x in xrange(5)]
Vous pouvez maintenant ajouter des éléments à la liste:
Matrix[0][0] = 1
Matrix[4][0] = 5
print Matrix[0][0] # prints 1
print Matrix[4][0] # prints 5
à partir d'ici: Comment définir un tableau à deux dimensions en python
Que dis-tu de ça:
class MultiDimList(object):
def __init__(self, shape):
self.shape = shape
self.L = self._createMultiDimList(shape)
def get(self, ind):
if(len(ind) != len(self.shape)): raise IndexError()
return self._get(self.L, ind)
def set(self, ind, val):
if(len(ind) != len(self.shape)): raise IndexError()
return self._set(self.L, ind, val)
def _get(self, L, ind):
return self._get(L[ind[0]], ind[1:]) if len(ind) > 1 else L[ind[0]]
def _set(self, L, ind, val):
if(len(ind) > 1):
self._set(L[ind[0]], ind[1:], val)
else:
L[ind[0]] = val
def _createMultiDimList(self, shape):
return [self._createMultiDimList(shape[1:]) if len(shape) > 1 else None for _ in range(shape[0])]
def __repr__(self):
return repr(self.L)
Vous pouvez ensuite l'utiliser comme suit
L = MultiDimList((3,4,5)) # creates a 3x4x5 list
L.set((0,0,0), 1)
L.get((0,0,0))
En voici une qui vous donnera une "matrice" à N dimensions, remplie de copies d’un objet copiable.
Edit : Ceci est une légère modification de la réponse originale de pterodragon, que je préfère de loin à la réponse moins lisible de user2114402. En fait, en dehors d'une chaîne de documentation, la seule différence par rapport à la solution de pterodragon est que j'utilise explicitement une liste de tailles de dimension, plutôt que de la faire passer par l'utilisateur en tant qu'argument.
import copy
def instantiate_mdl(dim_maxes, base=0):
""" Instantiate multi-dimensional list, that is a list of list of list ...
Arguments:
dim_maxes (list[int]): a list of dimension sizes, for example
[2, 4] represents a matrix (represented by lists) of 2 rows and
4 columns.
base (object): an optional argument indicating the object copies
of which will reside at the lowest level in the datastructure.
Returns:
base (list[base]): a multi-dimensional list of lists structure,
which is filled with clones of the base parameter.
"""
for dim_max in reversed(dim_maxes):
base = [copy.deepcopy(base) for i in range(dim_max)]
return base
data = instantiate_mdl([3, 5])
data[0][0] = 99999
data[1][1] = 88888
data[2][4] = 77777
for r in data:
print(r)
>>> # Output
>>> [99999, 0, 0, 0, 0]
>>> [0, 88888, 0, 0, 0]
>>> [0, 0, 0, 0, 77777]
Je suis étonné que personne n'ait essayé de concevoir un moyen générique de le faire .. Voir ma réponse ici: https://stackoverflow.com/a/33460217/5256940
import copy
def ndlist(init, *args): # python 2 doesn't have kwarg after *args
dp = init
for x in reversed(args):
dp = [copy.deepcopy(dp) for _ in xrange(x)] # Python 2 xrange
return dp
l = ndlist(0, 1, 2, 3, 4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1
Edit: Construit sur la réponse de user2114402: paramètre de valeur par défaut ajouté
def ndlist(s, v):
return [ndlist(s[1:], v) for i in xrange(s[0])] if s else v
En Python, j'ai créé une petite méthode factory pour créer une liste de dimensions et de tailles variables sur chacune de ces dimensions:
def create_n_dimensional_matrix(self, n):
dimensions = len(n)
if (dimensions == 1):
return [0 for i in range(n[0])]
if (dimensions == 2):
return [[0 for i in range(n[0])] for j in range(n[1])]
if (dimensions == 3):
return [[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])]
if (dimensions == 4):
return [[[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])] for l in range(n[3])]
lancez-le comme ça:
print(str(k.create_n_dimensional_matrix([2,3])))
print(str(k.create_n_dimensional_matrix([3,2])))
print(str(k.create_n_dimensional_matrix([1,2,3])))
print(str(k.create_n_dimensional_matrix([3,2,1])))
print(str(k.create_n_dimensional_matrix([2,3,4,5])))
print(str(k.create_n_dimensional_matrix([5,4,3,2])))
Quelles impressions:
Les listes à quatre dimensions (2x3x4x5), (5x4x3x2)
[[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, 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], [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, 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], [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, 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, 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, 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, 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, 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, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]]]
import copy
dimensions = 2, 3, 4
z = 0
genList = lambda size,value: [copy.deepcopy(value) for i in range(size)]
for i in dimensions: z = genList(i, z)
Une manière très simple et élégante est:
a = [([0] * 5) for i in range(5)]
a
[[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]]
Voici une façon plus générique de le faire.
def ndlist(shape, dtype=list):
t = '%s for v%d in xrange(shape[%d])'
cmd = [t % ('%s', i + 1, i) for i in xrange(len(shape))]
cmd[-1] = cmd[-1] % str(dtype())
for i in range(len(cmd) - 1)[::-1]:
cmd[i] = cmd[i] % ('[' + cmd[i + 1] + ']')
return eval('[' + cmd[0] + ']')
list_4d = ndlist((2, 3, 4))
list_3d_int = ndlist((2, 3, 4), dtype=int)
print list_4d
print list_3d_int
Résultat:
[[[[], [], [], []], [[], [], [], []], [[], [], [], []]], [[[], [], [], []], [[], [], [], []], [[], [], [], []]]]
[[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]