Question [Fonction] Inverser une hashtable

Plus d'informations
il y a 1 an 3 mois - il y a 1 mois 1 semaine #29863 par Laurent Dardenne
On peut parfois souhaiter déclarer une hashtable (clé=valeur) et tout en créant l'inverse ( valeur=clé). Par exemple :
$h=@{
'un'=1
}

#et

$h2=@{
1='un'
}
Ce qui permet de manipuler une information soit d'après son nom soit d'après sa valeur qui lui est attribuée :
$key='un'
$H.$key
$key='1'
$H2.$key

L'inconvénient ici est que cette approche doit créer 2 variables, là où le C# par exemple propose des indexers .
Les classes Powershell permettent ce type de construction (voir chapitre 6.5 Indexeur) mais cela nécessite qq connaissances supplémentaires.
De plus on peut encore trouver des environnements en PS v3.0 ou v4.0 ( ce qui est mon cas et je ne peux ni charger de dll ni utiliser Add-Type).

On reprend donc les bases de Powershell, ici ETS, tout en codant simplement. Ce qui nous donne ceci:
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.Collections.Hashtable</Name>
<Members>
<ScriptMethod>
<Name>Reverse</Name>
<!-- Les types primitifs sont :
Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double et Single.
-->
<Script>
$ReverseHashtable=@{}

Foreach ($Current in $this.GetEnumerator())
{
$Key=$Current.Key
$Value=$Current.Value
if ($null -eq $Value)
{ Throw "Impossible to reverse the hashtable. The key '$Key' has a value null.The value of a key cannot be null." }
$ValueType=$Value.Gettype()
if ( ($Value -is [string]) -or $ValueType.isPrimitive)
{
try {
$ReverseHashtable.Add($Current.Value,$Key)
} catch [System.ArgumentException] {
Throw "Impossible to reverse the hashtable. Key values '$($Current.Value)' are duplicated."
}
}
else
{ Throw "Impossible to reverse the hashtable. The value '$Key' is not a scalar or a string :'$ValueType'." }
}
return ,$ReverseHashtable
</Script>
</ScriptMethod>
</Members>
</Type>
<Type>
<Name>System.Collections.Specialized.OrderedDictionary</Name>
<Members>
<ScriptMethod>
<Name>Reverse</Name>
<Script>
if ($this.IsReadOnly)
{ $ReverseHashtable=[ordered]@{} }
else
{ $ReverseHashtable=@{} }

Foreach ($Current in $this.GetEnumerator())
{
$Key=$Current.Key
$Value=$Current.Value
if ($null -eq $Value)
{ Throw "Impossible to reverse the hashtable. The key the key '$Key' has a value null.The value of a key cannot be null." }
$ValueType=$Value.Gettype()

if ( ($Value -is [string]) -or $ValueType.isPrimitive)
{
try {
$ReverseHashtable.Add($Current.Value,$Key)
} catch [System.ArgumentException] {
Throw "Impossible to reverse the hashtable. Key values '$($Current.Value)' are duplicated."
}
}
else
{ Throw "Impossible to reverse the hashtable. The value of the key '$Key' is not a scalar or a string :'$ValueType'." }
}

if ($this.IsReadOnly)
{ return ,$ReverseHashtable.AsReadOnly() }
return ,$ReverseHashtable
</Script>
</ScriptMethod>
</Members>
</Type>
</Types>

Ce qui reste accessible je pense.

On duplique le code car on doit déclarer les types 'System.Collections.Hashtable' et 'System.Collections.Specialized.OrderedDictionary'.
La présence du second type est liée à cette astuce .

Ce qui autorise, à partir d'un hashtable en ReadOnly, la création d'un hashtable inversée et toujours en ReadOnly.

Une fois enregistré ce fichier, on l'utilise ainsi :
$File='..\System.Collections.Hashtable.ps1xml'
Update-TypeData -PrependPath $File

$h=@{
'un'=1
'deux'=2
'trois'=3
}

$h.Reverse()
# Name Value
# ---- -----
# 3 trois
# 2 deux
# 1 un

Les cas d'erreur étant :
$h=@{
'un'=1
'deux'=2
'trois'=$Null
}
$h2=$h.Reverse()
#Exception lors de l'appel de «Reverse» avec «0» argument(s): «Impossible to reverse the hashtable.
#The key 'trois' has a value null.The value of a key cannot be null.»
#
#Une clé de hashtable ne peut être $null

$h=@{
'un'=1
'deux'=2
'trois'=1
}
$h2=$h.Reverse()
#Exception lors de l'appel de «Reverse» avec «0» argument(s): «Impossible to reverse the hashtable.
#Key values '1' are duplicated.»
#
#les valeurs devenant des clés on ne peut dupliquer un nom de clé

$h=@{
'un'=1
'deux'=(get-item 'G:\PS\Hashtable\Reverse.Tests.ps1') #$PSCommandPath)
'trois'=3
}
$h2=$h.Reverse()
#Exception lors de l'appel de «Reverse» avec «0» argument(s): «Impossible to reverse the hashtable.
#The value 'deux' is not a scalar or a string :'System.IO.FileInfo'.»
#
#Pour un usage sous Powershell on évite ce type de construction.


Une fonction identique qui ne s'appuie pas sur ETS :
function New-ReversedHashtable {
param($Hashtable)

if(-not ( ($Hashtable -is [System.Collections.Hashtable]) -OR ($Hashtable-is [System.Collections.Specialized.OrderedDictionary])) )
{ Throw "The argument `$Hashtable([$($Hashtable.GetType().Fullname)]) the argument must be one of the following types : [System.Collections.Hashtable], [System.Collections.Specialized.OrderedDictionary]" }
$isReadOnly=$Hashtable.IsReadOnly

if ($isReadOnly)
{ $ReverseHashtable=[ordered]@{} }
else
{ $ReverseHashtable=@{} }

Foreach ($Current in $Hashtable.GetEnumerator())
{
$Key=$Current.Key
$Value=$Current.Value
if ($null -eq $Value) #ArgumentNullException
{ Throw "Impossible to reverse the hashtable. The key '$Key' has a value null.The value of a key cannot be null." }
$ValueType=$Value.Gettype()

if ( ($Value -is [string]) -or $ValueType.isPrimitive)
{
try {
$ReverseHashtable.Add($Current.Value,$Key)
} catch [System.ArgumentException] { #ArgumentException
Throw "Impossible to reverse the hashtable. Key values '$($Current.Value)'' are duplicated."
}
}
else
{ Throw "Impossible to reverse the hashtable. The value of the key '$Key' is not a scalar or a string :'$ValueType'." }
}

if ($isReadOnly)
{ return ,$ReverseHashtable.AsReadOnly() }
return ,$ReverseHashtable
}

Mais j’entends une personne au fond de la salle près du radiateur qui me dit "Comment inverser une hashtable générique ?"
Exemple :
$h = new-object 'System.Collections.Generic.Dictionary[String,Int]'
$h.'Un'=1
$h.'Deux'=2
$h.'Trois'=3

Bha, c'est un autre sujet (*).
;-)
$KeyDelegate = [Func[[System.Collections.Generic.KeyValuePair[String,Int]],String]]{ $args[0].Key }
$ValueDelegate = [Func[[System.Collections.Generic.KeyValuePair[String,Int]],Int]]{ $args[0].Value}
$Result=[Linq.Enumerable]::ToDictionary($h, $ValueDelegate,$KeyDelegate)
$Result.GetType().Fullname
$Result

Powershell c'est facile, mais ce n'est pas tout les jours facile...

Note: je n'ai pas de lien sur ETS (Extended Type System) à proposer car MS joue au bonneteau avec la doc de Powershell et surtout avec ce sujet.

*
Le sujet étant d'inverser n'importe quel type de hashtable générique, voir d'utiliser d'autres types avec la méthode [Linq.Enumerable]::ToDictionary
---

Tutoriels PowerShell
Dernière édition: il y a 1 mois 1 semaine par Laurent Dardenne. Raison: Correction du code suivant : if ( ($ValueType -isnot [string]) -and $ValueType.isPrimitive)

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 mois 1 semaine #30344 par Laurent Dardenne
En attendant un tutoriel sur l'usage des génériques avec Powershell, voici une première ébauche :
function Inverse{
    param(
        $InputObject
    )

     #On manipule des informations du type
    $SourceType=$InputObject.GetType()

    if ($SourceType.IsGenericType -eq $false)
    { Throw 'InputObject doit être un type générique.' }
    
     # On distingue les deux erreurs
    if ($SourceType.IsGenericTypeDefinition -eq $true)
    { Throw 'InputObject doit être un type générique fermé.' }

     #On cherche à savoir si $inputObject implémente l'interface générique
     # IDictionary<TKey,TValue> ( qui elle même implémente System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>)

    $isIDictionaryImplemented=$InputObject.GetType().GetInterfaces().Where({
        if ($_.isGenericType)
        { $_.GetGenericTypeDefinition().fullname -eq 'System.Collections.Generic.IDictionary`2'}
    }).Count -eq 1

    # Note MsDoc : 
    #   L'interface IDictionary<TKey,TValue> est l’interface de base pour les collections génériques de paires clé/valeur.
    #   Chaque élément est une paire clé/valeur stockée dans un KeyValuePair<TKey,TValue> objet.

    if ($isIDictionaryImplemented -eq $false)
    { Throw 'InputObject n''est pas une collection générique de paires clé/valeur (IDictionary<TKey,TValue>).' }

     #On récupère les types utilisés pour créer la 'hashtable' générique ( TODO : le type peut être différent)
    $GenericArguments=$InputObject.GetType().GetGenericArguments()

    #Crée un type ouvert à partir de la classe System.Collections.Generic.KeyValuePair
    #Ici on sait que ce type générique à deux arguments de type; cf. 'System.Collections.Generic.IDictionary`2'
    $KeyValuePairType=[Type]'System.Collections.Generic.KeyValuePair`2'
    Write-debug "KeyValuePairType : $($KeyValuePairType.ToString())"
    Write-debug "KeyValuePairType est un type ouvert ? $($KeyValuePairType.IsGenericTypeDefinition -eq $true)"

     #Crée un type fermé (exemple: System.Collections.Generic.KeyValuePair<String,Int> ) à partir des arguments de type de $InputObject
     #C'est une classe générique différente mais les types des arguments sont identiques
    $DelegateInputParameterType=$KeyValuePairType.MakeGenericType($GenericArguments)
    Write-debug "DelegateInputParameter : $($DelegateInputParameterType.ToString())"
    Write-debug "DelegateInputParameter est un type fermé ? $($DelegateInputParameterType.IsGenericTypeDefinition -eq $false)"

    #On crée les foncteurs nécessaires pour manipuler les argument de types de $InputObject
    #on sait, d'après 'System.Collections.Generic.IDictionary`2', que le functor à deux arguments de type
    $FunctorType=[Type]'Func`2'

     #L'ordre de la liste des paramètres correspond à celui
     # indiqué lors de la création de l'objet
    [Type[]] $ParametersType=@($DelegateInputParameterType,$GenericArguments[0])
    $KeyDelegateType=$FunctorType.MakeGenericType($ParametersType)
    Write-debug "Foncteur pour KeyDelegateType : $($KeyDelegateType)"

    [Type[]] $ParametersType=@($DelegateInputParameterType,$GenericArguments[1])
    $ValueDelegateType=$FunctorType.MakeGenericType($ParametersType)
    Write-debug "Foncteur pour ValueDelegateType : $($ValueDelegateType)"

     #Cast nécessaire des scriptblocks
    $KeyDelegate =  { $args[0].Key } -as $KeyDelegateType
    $ValueDelegate ={ $args[0].Value} -as $ValueDelegateType

    #Bien que le paramètre $InputObject ne soit pas typé dans l'entête de la fonction, on manipule un PSObject
    #on doit donc récupérer l'objet encapsulé via la propriété PsObject.BaseObject
    #Sinon on a une erreur d'appel
    #
    #L'ordre des délégués est ici inversé puisque c'est l'objectif : la valeur devient la clé et inversement
    $Result=[Linq.Enumerable]::ToDictionary($InputObject.PsObject.BaseObject, $ValueDelegate,$KeyDelegate)
    ,$Result
}

$h = new-object 'System.Collections.Generic.Dictionary[String,Int]'
$h.'Un'=1
$h.'Deux'=2
$h.'Trois'=3

$Result=Inverse $h
$Result
# Key Value
# --- -----
#   1 Un
#   2 Deux
#   3 Trois

$h2 = new-object 'System.Collections.Generic.Dictionary[Int,String]'
$h2.Add(1,'Un')
$h2.Add(2,'Deux')
$h2.Add(3,'Trois')
$Result=Inverse $h2
$Result
# Key   Value
# ---   -----
# Un        1
# Deux      2
# Trois     3

#Similaire à [Ordered]}
$SL = new-object 'System.Collections.Generic.SortedList[String,Int]'
$SL.Add("Un", 1)
$SL.Add("Deux", 2)
$SL.Add("Trois", 3)

$Result=Inverse $SL
$Result
Le dernier résultat n'est pas du type attendu (system.collections.Generic.SortedList[Int,String]), un jeu de test Pester serait le bienvenue :-)
Si ce sujet vous intéresse et en attendant la finalisation du tutoriel sur les génériques, vous pouvez consulter cet article : www.red-gate.com/simple-talk/dotnet/net-...nce-powershell-linq/

A suivre :-)

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 8 mois 6 jours #30353 par Laurent Dardenne
Une solution au dernier point, convertir le résultat d'appel de [Linq.Enumerable]::ToDictionary dans le type d'origine en inversant ses arguments.
On peut utiliser cette mécanique de conversion .
Car si on consulte la documentation des classes génériques implémentant IDictionary<TKey,TValue>, on constate qu'elles proposent toutes un constructeur attendant un IDictionnary générique.

Pour cette partie on utilise une string contenant le nom de type :
$Result=[Linq.Enumerable]::ToDictionary($InputObject.PsObject.BaseObject, $ValueDelegate,$KeyDelegate)
if ("$SourceType" -notmatch '^System\.Collections\.Generic\.Dictionary\[')
{
    #On récupère le 'nom court' du type : FullClassName[String,Int]
    # On n'utilise pas ici le système de réflexion de dotNet.
   $TargetTypeName="$SourceType"

    #On inverse <TKey,TValue> pour avoir <TValue,TKey>
    #Note:  on suppose que TKey,TValue ne sont pas des types génériques
   $TargetTypeName=$TargetTypeName -replace '^(.*?)\[(.*?),(.*)\]$','$1[$3,$2]'

   Write-Debug "Tente un transtypage à la Powershell vers le type $TargetTypeName"
   #Peut appeler un constructeur utilisant un dictionnaire générique en paramètre.
   #Cf. https://devblogs.microsoft.com/powershell/understanding-powershells-type-conversion-magic/
   $Result=$Result -as [Type]$TargetTypeName

   If ($null -eq $Result)
   { Throw "Impossible to cast the type '$($Result.Gettype())' to  '$TargetTypeName'." }
}
La version modifiée :
function Inverse{
    param(
        $InputObject
    )

     #On manipule des informations du type
    $SourceType=$InputObject.GetType()

    if ($SourceType.IsGenericType -eq $false)
    { Throw 'InputObject doit être un type générique.' }

     # On distingue les deux erreurs
    if ($SourceType.IsGenericTypeDefinition -eq $true)
    { Throw 'InputObject doit être un type générique fermé.' }

     #On cherche à savoir si $inputObject implémente l'interface générique
     # IDictionary<TKey,TValue> ( qui elle même implémente System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>)
    $isIDictionaryImplemented=$InputObject.GetType().GetInterfaces().Where({
        if ($_.isGenericType)
        { $_.GetGenericTypeDefinition().fullname -eq 'System.Collections.Generic.IDictionary`2'}
    }).Count -eq 1
    # Note MsDoc :
    #   L'interface IDictionary<TKey,TValue> est l'interface de base pour les collections génériques de paires clé/valeur.
    #   Chaque élément est une paire clé/valeur stockée dans un KeyValuePair<TKey,TValue> objet.

    if ($isIDictionaryImplemented -eq $false)
    { Throw 'InputObject n''est pas une collection générique de paires clé/valeur (IDictionary<TKey,TValue>).' }

     #On récupère les types utilisés pour créer la 'hashtable' générique ( TODO : le type peut être différent)
    $GenericArguments=$InputObject.GetType().GetGenericArguments()

    #Crée un type ouvert à partir de la classe System.Collections.Generic.KeyValuePair
    #Ici on sait que ce type générique à deux arguments de type; cf. 'System.Collections.Generic.IDictionary`2'
    $KeyValuePairType=[Type]'System.Collections.Generic.KeyValuePair`2'
    Write-debug "KeyValuePairType : $($KeyValuePairType.ToString())"
    Write-debug "KeyValuePairType est un type ouvert ? $($KeyValuePairType.IsGenericTypeDefinition -eq $true)"

     #Crée un type fermé (exemple: System.Collections.Generic.KeyValuePair<String,Int> ) à partir des arguments de type de $InputObject
    #C'est une classe générique différente mais les types des arguments sont identiques
    $DelegateInputParameterType=$KeyValuePairType.MakeGenericType($GenericArguments)
    Write-debug "DelegateInputParameter : $($DelegateInputParameterType.ToString())"
    Write-debug "DelegateInputParameter est un type fermé ? $($DelegateInputParameterType.IsGenericTypeDefinition -eq $false)"

    #On crée les foncteurs nécessaires pour manipuler les argument de types de $InputObject
    #on sait, d'après 'System.Collections.Generic.IDictionary`2', que le functor à deux arguments de type
    $FunctorType=[Type]'Func`2'

     #L'ordre de la liste des paramètres correspond à celui
     # indiqué lors de la création de l'objet
    [Type[]] $ParametersType=@($DelegateInputParameterType,$GenericArguments[0])
    $KeyDelegateType=$FunctorType.MakeGenericType($ParametersType)
    Write-debug "Foncteur pour KeyDelegateType : $($KeyDelegateType)"

    [Type[]] $ParametersType=@($DelegateInputParameterType,$GenericArguments[1])
    $ValueDelegateType=$FunctorType.MakeGenericType($ParametersType)
    Write-debug "Foncteur pour ValueDelegateType : $($ValueDelegateType)"

     #Cast nécessaire des scriptblocks
    $KeyDelegate =  { $args[0].Key } -as $KeyDelegateType
    If ($null -eq $KeyDelegate)
    { Throw "Impossible to cast the 'Key' scriptblock to '$KeyDelegateType'."}

    $ValueDelegate ={ $args[0].Value} -as $ValueDelegateType
    If ($null -eq $ValueDelegate)
    { Throw "Impossible to cast the 'Value' scriptblock to '$ValueDelegate'."}


    #Bien que le paramétre $InputObject ne soit pas typé dans l'entête de la fonction, on manipule un PSObject
    #on doit donc récupérer l'objet encapsulé via la propriété PsObject.BaseObject
    #Sinon on a une erreur d'appel
    #
    #L'ordre des délégués est ici inversé puisque c'est l'objectif : la valeur devient la clé et inversement
    $Result=[Linq.Enumerable]::ToDictionary($InputObject.PsObject.BaseObject, $ValueDelegate,$KeyDelegate)
    if ("$SourceType" -notmatch '^System\.Collections\.Generic\.Dictionary\[')
    {
        #On récupère le 'nom court' du type : FullClassName[String,Int]
        # On n'utilise pas ici le système de réflexion de dotNet.
       $TargetTypeName="$SourceType"
        #On inverse <TKey,TValue> pour avoir <TValue,TKey>
        #Note:  on suppose que TKey,TValue ne sont pas des types génériques
        #       IDictionary<typeof(T), T> est impossible.
       $TargetTypeName=$TargetTypeName -replace '^(.*?)\[(.*?),(.*)\]$','$1[$3,$2]'

       Write-Debug "Tente un transtypage à la Powershell vers le type $TargetTypeName"
       #Peut appeler un constructeur utilisant un dictionnaire génèrique en paramètre.
       #Cf. https://devblogs.microsoft.com/powershell/understanding-powershells-type-conversion-magic/
       $Result=$Result -as [Type]$TargetTypeName
       If ($null -eq $Result)
       { Throw "Impossible to cast the type '$($Result.Gettype())' to  '$TargetTypeName'." }
    }
    Write-Output $Result -NoEnumerate
}

$h = new-object 'System.Collections.Generic.Dictionary[String,Int]'
$h.'Un'=1
$h.'Deux'=2
$h.'Trois'=3

$Result=Inverse $h
$Result
# Key Value
# --- -----
#   1 Un
#   2 Deux
#   3 Trois
"$($Result.GetType())"
#System.Collections.Generic.Dictionary[int,string]

$h2 = new-object 'System.Collections.Generic.Dictionary[Int,String]'
$h2.Add(1,'Un')
$h2.Add(2,'Deux')
$h2.Add(3,'Trois')
$Result=Inverse $h2
$Result
# Key   Value
# ---   -----
# Un        1
# Deux      2
# Trois     3
"$($Result.GetType())"
#System.Collections.Generic.Dictionary[string,int]


#Similaire à [Ordered]
#ou a System.Collections.Generic.SortedDictionary<TKey,TValue>
$SL = new-object 'system.collections.Generic.SortedList[String,Int]'
$SL.Add("Un", 1)
$SL.Add("Deux", 2)
$SL.Add("Trois", 3)

$Result=Inverse $SL
$Result
"$($Result.GetType())"
#System.Collections.Generic.SortedList[int,string]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 2 mois 6 jours - il y a 2 mois 4 jours #31102 par Boelpaep
Réponse de Boelpaep sur le sujet [Fonction] Inverser une hashtable
renverser la key et value:

Si

le variable que vous voulez reverser sapelle $myvar:
$myvar=@{"a"="1";"b"="2";"c"=3;"d"=$null;"e"=3;"f"="1";} #sample data

Alors

$myrev=@{};$myvar.keys|%{if($myvar[$_] -match '^[a-z0-9]+$'){$myrev[$myvar[$_]]=$_}};$myvar=$myrev

renversera votre variable

explication:
#sample data $myrev=@{}; # create temporary variable
$myvar.keys|%{
if($myvar[$_] -match '^[a-z0-9]+$'){$myrev[$myvar[$_]]=$_} #invert key<> value if value is alphanumeric otherwise throw away
};
$myvar=$myrev # copy temp var to initial variable


Alternative qui donne du feedback et autonumérote les duplicates


$mytmp=@{}  # temporary variable that stores 
$myrev=@{}; # create reverse destination variable
$dedup=@{}; # helper variable

# Clean values : remove non alphanumeric values + autonumber duplicate values AND put in temp variable
$myvar.keys|%{ #clean values (duplicates and no alphnumeric)
$val=[string]$myvar[$_]
    if($val -match '^[a-z0-9]+$'){ #copy keyvalue pairs that are alphnumeric
        $dedup[$val]=1+$dedup[$val]; # Alter value if it is a duplicate
        if($dedup[$val] -gt 1) {$mytmp[$_]=$val+"_"+$dedup[$val];"Duplicate detected on key($_)/val($val), renamed value!"} 
        else {$mytmp[$_]=$val;} 
    } else {"Non Alphanumeric value detected! on key '$_', value and key will be removed"} #
}

$mytmp.keys|%{$myrev[$mytmp[$_]]=$_} #invert clean array : key<> value and store in $myrev (myreversed variable)
Dernière édition: il y a 2 mois 4 jours par Boelpaep. Raison: J'ai ajouter un if notmatch pour verifier que le value peut etre utiliser comme cléf d'un hashtable

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 2 mois 6 jours #31103 par Laurent Dardenne
Salut,
$env n'existe pas.
En cas de duplication de valeur, il y a une perte d'information et si une des valeurs vaut $null il y a une exception. je n'ai pas testé avec des valeurs ayant un type qui n'est pas scalaire.
Ton code fonctionne si on sait que ces 3 points ne se présenteront pas.

L'objectif état d'avoir 2 hashtables :
On peut parfois souhaiter déclarer une hashtable (clé=valeur) et tout en créant l'inverse

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 2 mois 6 jours - il y a 2 mois 6 jours #31104 par Boelpaep
Réponse de Boelpaep sur le sujet [Fonction] Inverser une hashtable
Bonjour,

Probleme 1/3 (erreure de code reparé dans la source)
En effet $env devait etre $myvar je l'ai corriger dans mon code

Probleme 2/3 (normalle)
Pour ce qui est de valeurs duplication, se sera toujours le cas, un dictionary key doit toujours etre unique, donc les values qui existent déja peuvent seulement occupé une seule key

Probleme 3/3
resolu avec un If match pour verifié si le value est alphanumeric, tout le reste peut pas etre utilisé en tant que key

(code adaptéé dans mon post initiel)

"lobjectif cetait davoir deux hash" ils sont la, $myvar et $myrev (my reverse) il suffit de pas utiliser ma dernierre ligne code dexecution $myvar=$myrev
Dernière édition: il y a 2 mois 6 jours par Boelpaep.

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.095 secondes
Propulsé par Kunena