Question
Copie d'une table contenant des objets (deep-copy)
- crystof
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
Réduire
Plus d'informations
- Messages : 11
- Remerciements reçus 0
il y a 15 ans 10 mois #6615
par crystof
Copie d'une table contenant des objets (deep-copy) a été créé par crystof
Bonjour à tous,
Voila, j'essaye de passer en paramétre une table qui contient des objets (psobject) et visiblement le passage de paramétre se fait par référence.
J'essaye donc de mettre en place une copie de ma table d'origine (via clone), car je souhaite modifier des champs sans modifier la table de depart (ce que je ne parviens pas à faire : chaque affectation recopie l'adresse de l'objet sans créer un nouvel objet.

Pour tester je me suis bati un prototype cf ci-dessous
Pour résumer comment faire une sorte de Deep-Copy ?
merci de votre aide/suggestions
[code:1]
function NewObjectProps ( $JName, $JType, $Other ){
$Obj=New-Object PSobject
$Obj | Add-Member Noteproperty JName $JName
$Obj | Add-Member Noteproperty JType $JType
$Obj | Add-Member Noteproperty Jlnk $Other
return $Obj
}
function TestParam ( $Collection ){
$Collection[1].Jname=\"MODIF\" # modif de l'un des paramétres
}
function TestDeepCopy ( [System.Collections.ArrayList]$Collection ){
$Clone= New-Object System.Collections.ArrayList
for( $i=0; $i -lt $Collection.count; $i++ ){
[Void]$Clone.add($Collection[$i].clone)
}
# ko $Clone[1].Jname=\"DEEPMODIF\" # test modif de l'un des paramétres
}
# test init
$LinksCollection=@{}
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name1 -JType tot1 -Other lil1)
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name2 -JType tot2 -Other lil2)
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name3 -JType tot3 -Other lil3)
# test passage de parametre et modif
Write-Host AVANT: $LinksCollection.Values
TestParam $LinksCollection[\"test1\"]
Write-Host APRES-TESTPARAM: $LinksCollection.Values # le champ a été modifié
# test deep-copy
$LinksCollection[\"test1\"][1].jname=\"name2\" # re-init pour le test
TestDeepCopy $LinksCollection[\"test1\"]
Write-Host APRES-DEEPCOPY: $LinksCollection.Values # le champ a t'il été modifié ?
[/code:1]
Voila, j'essaye de passer en paramétre une table qui contient des objets (psobject) et visiblement le passage de paramétre se fait par référence.
J'essaye donc de mettre en place une copie de ma table d'origine (via clone), car je souhaite modifier des champs sans modifier la table de depart (ce que je ne parviens pas à faire : chaque affectation recopie l'adresse de l'objet sans créer un nouvel objet.
Pour tester je me suis bati un prototype cf ci-dessous
Pour résumer comment faire une sorte de Deep-Copy ?
merci de votre aide/suggestions
[code:1]
function NewObjectProps ( $JName, $JType, $Other ){
$Obj=New-Object PSobject
$Obj | Add-Member Noteproperty JName $JName
$Obj | Add-Member Noteproperty JType $JType
$Obj | Add-Member Noteproperty Jlnk $Other
return $Obj
}
function TestParam ( $Collection ){
$Collection[1].Jname=\"MODIF\" # modif de l'un des paramétres
}
function TestDeepCopy ( [System.Collections.ArrayList]$Collection ){
$Clone= New-Object System.Collections.ArrayList
for( $i=0; $i -lt $Collection.count; $i++ ){
[Void]$Clone.add($Collection[$i].clone)
}
# ko $Clone[1].Jname=\"DEEPMODIF\" # test modif de l'un des paramétres
}
# test init
$LinksCollection=@{}
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name1 -JType tot1 -Other lil1)
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name2 -JType tot2 -Other lil2)
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name3 -JType tot3 -Other lil3)
# test passage de parametre et modif
Write-Host AVANT: $LinksCollection.Values
TestParam $LinksCollection[\"test1\"]
Write-Host APRES-TESTPARAM: $LinksCollection.Values # le champ a été modifié
# test deep-copy
$LinksCollection[\"test1\"][1].jname=\"name2\" # re-init pour le test
TestDeepCopy $LinksCollection[\"test1\"]
Write-Host APRES-DEEPCOPY: $LinksCollection.Values # le champ a t'il été modifié ?
[/code:1]
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 15 ans 10 mois #6619
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Copie d'une table contenant des objets (deep-copy)
Salut,
la classe PscustomObject n'implémente pas l'interface ICloneable :
[code:1][PSCustomobject].GetInterfaces()
#
#IsPublic IsSerial #Name BaseType
#
----
#True False IFormattable
#True False IComparable[/code:1]
Il faut procéder autrement :
[code:1]
$LinksCollection=@{}
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name1 -JType tot1 -Other lil1)
$LinksCollection[\"test1\"]+=(NewObjectProps -JName name2 -JType tot2 -Other lil2)
$LinksCollection[\"test1\"]+=(NewObjectProps -JName name3 -JType tot3 -Other lil3)
$Clone=@{}
#Copie toutes les propriétés de chaque élément du tableau
$Clone[\"test1\"]+=@($LinksCollection[\"test1\"]|% {$_|select *})
$Clone[\"test1\"][0].JName=\"Modif\"
$LinksCollection[\"test1\"][1].Jlnk=\"Modif\"
$LinksCollection.Values
$Clone.Values
[/code:1]
Je te laisse adapter la copie de l'intégralité de la hashtable.
Mais ceci n'est tjr pas une copie en profondeur, car les membres synthétiques autres que les propriétés ne sont pas copiées. Par exemple un membre de type ScriptProperty est recopié en tant que NoteProperty, il y a une perte d'information.
La notion de Deep-copy sous PowerShell est donc différente de celle liée aux langages statiques.<br><br>Message édité par: Laurent Dardenne, à: 28/04/10 11:42
la classe PscustomObject n'implémente pas l'interface ICloneable :
[code:1][PSCustomobject].GetInterfaces()
#
#IsPublic IsSerial #Name BaseType
#
----
#True False IFormattable
#True False IComparable[/code:1]
Il faut procéder autrement :
[code:1]
$LinksCollection=@{}
$LinksCollection[\"test1\"]+=@(NewObjectProps -JName name1 -JType tot1 -Other lil1)
$LinksCollection[\"test1\"]+=(NewObjectProps -JName name2 -JType tot2 -Other lil2)
$LinksCollection[\"test1\"]+=(NewObjectProps -JName name3 -JType tot3 -Other lil3)
$Clone=@{}
#Copie toutes les propriétés de chaque élément du tableau
$Clone[\"test1\"]+=@($LinksCollection[\"test1\"]|% {$_|select *})
$Clone[\"test1\"][0].JName=\"Modif\"
$LinksCollection[\"test1\"][1].Jlnk=\"Modif\"
$LinksCollection.Values
$Clone.Values
[/code:1]
Je te laisse adapter la copie de l'intégralité de la hashtable.
Mais ceci n'est tjr pas une copie en profondeur, car les membres synthétiques autres que les propriétés ne sont pas copiées. Par exemple un membre de type ScriptProperty est recopié en tant que NoteProperty, il y a une perte d'information.
La notion de Deep-copy sous PowerShell est donc différente de celle liée aux langages statiques.<br><br>Message édité par: Laurent Dardenne, à: 28/04/10 11:42
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- crystof
- Auteur du sujet
- Hors Ligne
- Nouveau membre
-
Réduire
Plus d'informations
- Messages : 11
- Remerciements reçus 0
il y a 15 ans 10 mois #6625
par crystof
Réponse de crystof sur le sujet Re:Copie d'une table contenant des objets (deep-copy)
Merci Laurent,
j'ai corrigé comme cela (si ça peut être utile à d'autres !):
[code:1]
function TestDeepCopy ( $Collection ){
$Clone= New-Object System.Collections.ArrayList
# Copie toutes les propriétés de chaque élément du tableau dans clone
[Void]$Clone.addrange( ($Collection|% {$_|select *}) )
$Clone[1].Jname=\"mamodif\" # test modif de l'un des paramétres
return $Clone
}[/code:1]
Mais on peut faire la copie directement à l'appel de la function, comme ça :
[code:1]
function TestDeepCopy ( $Collection ){
$Collection[1].Jname=\"cmodifie\" # test modif de l'un des paramétres
return $Collection
}
...../......
$clone=TestDeepCopy ($LinksCollection[\"test1\"] | ForEach-Object {$_|select *})
[/code:1]
C'est parfait, encore merci<br><br>Message édité par: crysto444, à: 28/04/10 11:40
j'ai corrigé comme cela (si ça peut être utile à d'autres !):
[code:1]
function TestDeepCopy ( $Collection ){
$Clone= New-Object System.Collections.ArrayList
# Copie toutes les propriétés de chaque élément du tableau dans clone
[Void]$Clone.addrange( ($Collection|% {$_|select *}) )
$Clone[1].Jname=\"mamodif\" # test modif de l'un des paramétres
return $Clone
}[/code:1]
Mais on peut faire la copie directement à l'appel de la function, comme ça :
[code:1]
function TestDeepCopy ( $Collection ){
$Collection[1].Jname=\"cmodifie\" # test modif de l'un des paramétres
return $Collection
}
...../......
$clone=TestDeepCopy ($LinksCollection[\"test1\"] | ForEach-Object {$_|select *})
[/code:1]
C'est parfait, encore merci<br><br>Message édité par: crysto444, à: 28/04/10 11:40
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 15 ans 10 mois #6629
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Copie d'une table contenant des objets (deep-copy)
crysto444 écrit:
crysto444 écrit:
Et le souci avec la première approche est qu'on 'perd' le type de la collection, elle renvoi un tableau et pas un arraylist.
L'implicite est souvent de mise avec PowerShell.
De rien.Merci Laurent
crysto444 écrit:
Oui, car la collection est recopiée comme expliqué iciMais on peut faire la copie directement à l'appel de la function, comme ça :
Et le souci avec la première approche est qu'on 'perd' le type de la collection, elle renvoi un tableau et pas un arraylist.
L'implicite est souvent de mise avec PowerShell.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
Temps de génération de la page : 0.048 secondes
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- Copie d'une table contenant des objets (deep-copy)