Aller au contenu

Copier un tableau de tableaux

Il existe deux types de copie entre deux tableaux :

  • la copie superficielle pour laquelle les deux tableaux sont des objets distincts mais les sous-tableaux du premier sont les mêmes objets que les sous-tableaux du second ;
  • la copie profonde pour laquelle tableaux et sous-tableaux sont des objets distincts.

Shallow copy (copie superficielle)

Définition

Deux matrices A et B seront copiées superficiellement lorsque :

  • les objets A et B contiennent les mêmes valeurs d'éléments ;
  • les objets A et B sont distincts ;
  • les sous-tableaux de A sont les mêmes objets que les sous-tableaux de B.

Les scripts suivants permettent de réaliser des copies superficielles.

  1. Copie des sous-tableaux :

    1
    2
    3
    4
    A = [ [1,2,3], [4,5,6], [7,8,9] ]
    B = [ [], [], []]
    for i in range(3):
        B[i] = A[i]
    

  2. Utilisation de la fonction list() :

    1
    2
    A = [ [1,2,3], [4,5,6], [7,8,9] ]
    B = list(A)
    

Remarque

Dans chacun de ces scripts, les booléens suivants valent True :

  • B is not A
  • B == A
  • B[0] is A[0]
  • B[1] is A[1]
  • B[2] is A[2]
Pythonnerie - Copie par tranche
1
2
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = A[:]

Deep copy (copie profonde)

Définition

Deux matrices A et B seront copiées en profondeur lorsque :

  • les objets A et B contiennent les mêmes valeurs d'éléments ;
  • les objets A et B sont distincts ;
  • les sous-tableaux de A sont des objets distincts des sous-tableaux de B

Pour réaliser une copie en profondeur d'une matrice, on peut :

  • soit concevoir son propre script,
  • soit utiliser la fonction pré-programmée deepcopy() présente dans le module copy :
1
2
3
from copy import deepcopy
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = deepcopy(A)

Avec ce script, les booléens suivants valent True :

  • B is not A
  • B[i] is not A[i] pour chaque i.

Compléments

On trouvera ici la documentation Python sur le module copy.

Exercice

On dispose d'une matrice carrée.

Sans utiliser le module copy, compléter la définition de la fonction copie_profonde() en utilisant uniquement des boucles et des affectations.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def copie_profonde(matrice):
    """
    matrice - list, matrice carrée (n*n)
    Sortie: list - renvoie une copie profonde de matrice
    """


##----- Programme de test -----##
if __name__ == '__main__":
    dimension = 5    
    A = [ [i*dimension + j for j in range(dimension)] for i in range(dimension)]

    B = copieProfonde(A)

    ##----- Vérification -----##
    print(A)
    print("B is A ?", B is A)
    print("B[0] is A[0] ?", B[0] is A[0])
    print("B a les mêmes valeurs d'éléments que A ?", B == A)
Une réponse possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def copie_profonde(matrice):
    """
    matrice - list, matrice carrée (n*n)
    Sortie: list - renvoie une copie profonde de matrice
    """
    result = []
    for ligne in matrice:
        ligne_result = []
        for element in ligne:
            ligne_result.append(element)
        result.append(ligne_result)
    return result

##----- Programme de test -----##
if __name__ == '__main__":
    dimension = 5    
    A = [ [i*dimension + j for j in range(dimension)] for i in range(dimension)]

    B = copieProfonde(A)

    ##----- Vérification -----##
    print(A)
    print("B is A ?", B is A)
    print("B[0] is A[0] ?", B[0] is A[0])
    print("B a les mêmes valeurs d'éléments que A ?", B == A)
Une autre réponse avec définition par compréhension
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def copie_profonde(matrice):
    """
    matrice - list, matrice carrée (n*n)
    Sortie: list - renvoie une copie profonde de matrice
    """
    n = len(matrice)
    return [ [matrice[i][j]  for j in range(n)] for i in range(n)]

##----- Programme de test -----##
if __name__ == '__main__":
    dimension = 5    
    A = [ [i*dimension + j for j in range(dimension)] for i in range(dimension)]

    B = copieProfonde(A)

    ##----- Vérification -----##
    print(A)
    print("B is A ?", B is A)
    print("B[0] is A[0] ?", B[0] is A[0])
    print("B a les mêmes valeurs d'éléments que A ?", B == A)

Remarque

Le module copy est évidemment plus complexe que cela. Il traite des cas plus généraux. Par exemple des tableaux de tableaux de tableaux...

Notre fonction est limitée aux copies profondes de tableaux de tableaux (matrices) mais ne descend pas plus en profondeur et ne conviendra donc pas pour des cas comme les tableaux de tableaux de tableaux.