web-dev-qa-db-fra.com

Copier en profondeur un tableau dans Angular 2 + TypeScript

J'ai un tableau d'objets qui est une entrée. Permet de l'appeler content.

En essayant de le copier en profondeur, il a toujours une référence au tableau précédent.

Je dois dupliquer ce tableau d'entrée et modifier une propriété de la partie dupliquée. 

Si longtemps que j'ai essayé différentes méthodes qui ont échoué.

Façon ES6: 

public duplicateArray() {
  arr = [...this.content]
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}

La manière slice

public duplicateArray() {
  arr = this.content.slice(0);
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}

Dans les deux, tous les objets du tableau ont status: 'Default'.

Quelle est la meilleure approche pour copier en profondeur le tableau dans Angular 2?

48
Joel Almeida

Vérifie ça:

  let cloned = source.map(x => Object.assign({}, x));
86
YD1m

Simple: 

let objCopy  = JSON.parse(JSON.stringify(obj));
24
Cameron Gilbert

Cela fonctionne pour moi: 

this.listCopy = Object.assign([], this.list);
13
kabus

La seule solution que j'ai trouvée (presque instantanément après avoir posé la question) est de parcourir le tableau et d'utiliser Object.assign()

Comme ça: 

public duplicateArray() {
  let arr = [];
  this.content.forEach((x) => {
    arr.Push(Object.assign({}, x));
  })
  arr.map((x) => {x.status = DEFAULT});
  return this.content.concat(arr);
}

Je sais que ce n'est pas optimal. Et je me demande s’il existe de meilleures solutions.

13
Joel Almeida

Une méthode propre de copie en profondeur des objets contenant des objets imbriqués consiste à utiliser la méthode cloneDeep de lodash.

Pour Angular, vous pouvez le faire comme ceci:

Installez lodash avec yarn add lodash ou npm install lodash.

Dans votre composant, importez cloneDeep et utilisez-le:

import * as cloneDeep from 'lodash/cloneDeep';
...
clonedObject = cloneDeep(originalObject);

C'est seulement 18kb ajoutés à votre construction, ce qui en vaut la peine.

J'ai également écrit un article ici , si vous avez besoin d'informations supplémentaires sur l'utilisation de cloneDeep de lodash.

5
BogdanC

Voici le mien. Ne fonctionne pas pour les cas complexes, mais pour un simple tableau d'objets, c'est suffisant.

  deepClone(oldArray: Object[]) {
    let newArray: any = [];
    oldArray.forEach((item) => {
      newArray.Push(Object.assign({}, item));
    });
    return newArray;
  }
1
Alex Beugnet

Ceci est une suggestion de Daria (voir le commentaire sur la question) qui fonctionne à partir de TypeScript 2.1 et fondamentalement clone chaque élément du tableau :

this.clonedArray = theArray.map(e => ({ ... e }));
1
Alexei

Vous pouvez également utiliser le projet GitHub ts-deepcopy , également disponible sur npm, pour cloner votre objet, ou simplement inclure l'extrait de code ci-dessous. 

/**
 * Deep copy function for TypeScript.
 * @param T Generic type of target/copied value.
 * @param target Target value to be copied.
 * @see Source project, ts-deepcopy https://github.com/ykdr2017/ts-deepcopy
 * @see Code pen https://codepen.io/erikvullings/pen/ejyBYg
 */
export const deepCopy = <T>(target: T): T => {
  if (target === null) {
    return target;
  }
  if (target instanceof Date) {
    return new Date(target.getTime()) as any;
  }
  if (target instanceof Array) {
    const cp = [] as any[];
    (target as any[]).forEach((v) => { cp.Push(v); });
    return cp.map((n: any) => deepCopy<any>(n)) as any;
  }
  if (typeof target === 'object' && target !== {}) {
    const cp = { ...(target as { [key: string]: any }) } as { [key: string]: any };
    Object.keys(cp).forEach(k => {
      cp[k] = deepCopy<any>(cp[k]);
    });
    return cp as T;
  }
  return target;
};
0
Erik Vullings
let originalArray :string[]  = ['one', 'two', 'Sc-fi'];
let cloneArray :string[]  = originalArray.concat([]);
0
Adam111p