web-dev-qa-db-fra.com

Python 2.7 créer une liste multidimensionnelle

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?

14
poop

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
[[[], [], [], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]]
16
Blckknght

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

4
user2114402

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

2
user1505695

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))
2
Konstantin

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]
1
darkhipo

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
1
pterodragon

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:

  1. Les listes à deux dimensions (2x3), (3x2)
  2. Les listes tridimensionnelles (1x2x3), (3x2x1)
  3. 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]]]]
    
1
Eric Leschinski
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)
1
Anton Guselnikov

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]]
1
awangenh

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]]]
0
Milad.H