2
votes

Tuples / ArrayListe des paires

J'essaie essentiellement de créer une liste de paires, ce qui s'avère extrêmement difficile

Avant que quiconque mentionne Hashtables, il y aura des doublons dont je ne me soucie pas.

Par exemple, si je fais

$b += @{"dog" = "horse"}

J'obtiens

Name                           Value
----                           -----
dog                            cat

ce qui est bien. Cependant, je ne parviens pas à ajouter des éléments similaires à

$b = @{"dog" = "cat"}

L'élément a déjà été ajouté. Clé dans le dictionnaire: 'dog' Clé ajoutée: 'dog'

J'essaie simplement de créer un tableau de données auquel je peux ajouter en utilisant quelque chose comme .Add () ou + = .


0 commentaires

4 Réponses :


2
votes

Je pense qu'une liste de tables de hachage devrait accomplir ce que vous recherchez.

$ht = @{foo='bar'}
$list = [System.Collections.Generic.List[hashtable]]::new()
$list.Add($ht)
$list.Add($ht)
$list.Add($ht)
$list


2 commentaires

Merci, mais j'obtiens l'erreur ci-dessous en essayant de définir l'invocation de la méthode $ list a échoué car [System.Collections.Generic.List1 [[System.Collections.Hashta‌ ble, mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]] ne contient pas de méthode nommée 'new'. À la ligne: 1 char: 1 + $ results = [System.Collections.Generic.List [hashtable]] :: new () + ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~ + CategoryInfo: InvalidOperation: (: ) [], RuntimeException + FullyQualifiedErrorId: MethodNotFound


Vous êtes alors sur une ancienne version de PowerShell. Vous devrez utiliser $ list = New-Object -TypeName 'System.Collections.Generic.List [hashtable]'



1
votes

La réponse utile de Persistent13 offre une solution efficace et efficiente - quoique légèrement obscure.

Créer un tableau de tables de hachage est la solution la plus simple, mais il est important de noter que "étendre" un tableau signifie implicitement le recréer , étant donné que les tableaux sont des structures de données de taille fixe, qui peuvent devenir un problème de performances avec de nombreuses itérations:

# Using array-construction operator ",", create a single-element array
# containing a hashtable
$b = , @{ dog = "cat"} 

# "Extend" array $b by appending another hashtable.
# Technically, a new array must be allocated that contains the original array's
# elements plus the newly added one.
$b += @{ dog = "horse"}

Ceci Le problème GitHub traite d'une éventuelle amélioration future pour que PowerShell prenne en charge nativement un type de données de type liste extensible de manière efficace ou pour qu'il soit par défaut à un tel type de données. (À partir de Windows PowerShell v5.1 / PowerShell Core 6.2.0, PowerShell utilise par défaut des tableaux de taille fixe, de type [object[ Oft[.... )).


0 commentaires

1
votes

Si vous voulez une liste de tuples, je vous recommande de créer une liste de tuples :

function New-Tuple {
    Param(
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [ValidateCount(2,20)]
        [array]$Values
    )

    Process {
        $types = ($Values | ForEach-Object { $_.GetType().Name }) -join ','
        New-Object "Tuple[$types]" $Values
    }
}

$tuples = ('dog', 'cat'), ('dog', 'horse') | New-Tuple

Notez que dans cet exemple $ list est un tableau régulier, ce qui signifie que , comme l'a souligné @ mklement0 dans sa réponse, en y ajoutant l'opérateur d'affectation + = recrée le tableau avec une taille augmentée de 1, place le nouvel élément dans le nouvel emplacement vide, puis remplace le tableau d'origine. Pour un petit nombre d'opérations d'ajout, ce n'est généralement pas un gros problème, mais avec un nombre croissant d'opérations d'ajout, l'impact sur les performances devient significatif.

Utiliser un ArrayList au lieu d'un simple array évite ce problème:

function New-Tuple {
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateCount(2,2)]
        [string[]]$Values
    )

    New-Object 'Tuple[String,String]' $Values
}

$tuple1 = New-Tuple 'dog', 'cat'
$tuple2 = New-Tuple 'dog', 'horse'

La méthode Add () des objets ArrayList renvoie l'index où l'élément a été ajouté . Out-Null supprime cette sortie qui est dans la plupart des cas indésirable. Si vous souhaitez travailler avec ces numéros d'index, vous pouvez les collecter dans une variable au lieu de les supprimer ( $ i = $ list.Add ($ t1) ).

Si vous voulez éviter d'avoir à spécifier le type d'un nouveau tuple tout le temps, vous pouvez l'envelopper dans une fonction réutilisable comme celle-ci:

$list = New-Object Collections.ArrayList

$tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
$tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'

$list.Add($tuple1) | Out-Null
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2

$list.Add($tuple2) | Out-Null
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2
# dog   horse      2

ou, d'une manière plus générique, comme ceci:

$list = @()

$tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
$tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'

$list += $tuple1
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2

$list += $tuple2
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2
# dog   horse      2


0 commentaires

0
votes

Merci à mklement0 comme ci-dessous est probablement la solution la plus simple

$ht = @{foo='bar'}
$list = [System.Collections.Generic.List[hashtable]]::new()
$list.Add($ht)
$list.Add($ht)
$list.Add($ht)
$list

Et la méthode de Persistent13 donne également un itinéraire facile

$b = , @{ dog = "cat"} 
$b += @{ dog = "horse"}

Je suppose que je était juste surpris qu'il n'y ait pas de moyen plus enraciné d'obtenir ce que je pense être un type d'objet assez basique / standard


0 commentaires