43 votes

Tableaux multidimensionnels de Powershell

J'ai une façon de faire des tableaux dans d'autres langages comme ceci :

$x = "David"
$arr = @()

$arr[$x]["TSHIRTS"]["SIZE"] = "M"

Cela génère une erreur.

1 votes

Comme cela a été souligné précédemment, le code que vous avez posté est un dictionnaire ou un hachage, et non un tableau commun.

61voto

manojlds Points 96599

Vous essayez de créer un tableau associatif (hachage). Essayez ce qui suit séquence de commandes

$arr=@{}
$arr["david"] = @{}
$arr["david"]["TSHIRTS"] = @{}    
$arr["david"]["TSHIRTS"]["SIZE"] ="M"
$arr.david.tshirts.size

Notez la différence entre les hachages et les tableaux

$a = @{} # hash
$a = @() # array

Les tableaux ne peuvent avoir que des entiers non négatifs comme index.

0 votes

Ça a marché comme un charme, mon pote ! Merci !

0 votes

S'agirait-il d'un exemple de table de hachage 3D ?

1 votes

Notez que les index négatifs sont significatifs dans Powershell. $arr[-1] est le dernier élément du tableau, $arr[-2] est l'avant-dernier, et ainsi de suite.

30voto

CB. Points 24549

De powershell.com :

PowerShell prend en charge deux types de tableaux multidimensionnels : les tableaux en dents de scie et les tableaux multidimensionnels réels.

Les tableaux en dents de scie sont des tableaux PowerShell normaux qui stockent des tableaux en tant qu'éléments. Il s'agit d'un stockage très rentable car les dimensions peuvent être de taille différente :

$array1 = 1,2,(1,2,3),3
$array1[0]
$array1[1]
$array1[2]
$array1[2][0]
$array1[2][1]

Les véritables tableaux multidimensionnels ressemblent toujours à une matrice carrée. Pour créer un tel tableau, vous devez accéder à .NET. La ligne suivante crée un tableau bidimensionnel de 10 et 20 éléments ressemblant à une matrice 10x20 :

$array2 = New-Object 'object[,]' 10,20
$array2[4,8] = 'Hello'
$array2[9,16] = 'Test'
$array2

pour un tableau de 3 dimensioanl 10*20*10

$array3 = New-Object 'object[,,]' 10,20,10

16voto

alistek Points 391

Pour prolonger ce que manojlds a dit ci-dessus, vous pouvez imbriquer des tables de hachage. Il ne s'agit peut-être pas d'un véritable tableau multidimensionnel, mais cela vous donne des idées sur la façon de structurer les données. Un exemple :

$hash = @{}

$computers | %{
    $hash.Add(($_.Name),(@{
        "Status" = ($_.Status)
        "Date"   = ($_.Date)
    }))
}

Ce qui est cool, c'est que vous pouvez faire référence à des choses comme :

($hash."Name1").Status

En outre, il est beaucoup plus rapide que les tableaux pour trouver des choses. Je l'utilise pour comparer des données plutôt que d'utiliser la correspondance dans les tableaux.

$hash.ContainsKey("Name1")

J'espère que cela vous aidera !

-Adam

13voto

iRon Points 41

Sachant que PowerShell pipe les objets entre les cmdlets Dans le cadre de PowerShell, il est plus courant d'utiliser un tableau de PSCustomObjects :

$arr = @(
    [PSCustomObject]@{Name = 'David';  Article = 'TShirt'; Size = 'M'}
    [PSCustomObject]@{Name = 'Eduard'; Article = 'Trouwsers'; Size = 'S'}
)

Ou pour les anciennes versions de PowerShell (PSv2) :

$arr = @(
    New-Object PSObject -Property @{Name = 'David';  Article = 'TShirt'; Size = 'M'}
    New-Object PSObject -Property @{Name = 'Eduard'; Article = 'Trouwsers'; Size = 'S'}
)

Et tapez votre sélection comme :

$arr | Where {$_.Name -eq 'David' -and $_.Article -eq 'TShirt'} | Select Size

Ou dans les versions plus récentes de PowerShell (Core) :

$arr | Where Name -eq 'David' | Where Article -eq 'TShirt' | Select Size

Ou (prenez juste la taille) :

$arr.Where{$_.Name -eq 'David' -and $_.Article -eq 'TShirt'}.Size

Addendum 2020-07-13

Syntaxe et lisibilité

Comme indiqué dans les commentaires, l'utilisation d'un tableau d'objets personnalisés est plus directe et permet d'économiser de la frappe. Si vous souhaitez aller plus loin, vous pouvez même utiliser la fonction ConvertForm-Csv (ou le Import-Csv ) pour construire le tableau :

$arr = ConvertFrom-Csv @'
Name,Article,Size
David,TShirt,M
Eduard,Trouwsers,S
'@

Ou plus lisible :

$arr = ConvertFrom-Csv @'
Name,   Article,   Size
David,  TShirt,    M
Eduard, Trouwsers, S
'@

<strong>Note : </strong>les valeurs qui contiennent des espaces ou des caractères spéciaux doivent être doublement citées.

Ou utiliser un cmdlet externe comme ConvertFrom-SourceTable qui lit les formats de table à largeur fixe :

$arr = ConvertFrom-SourceTable '
Name   Article   Size
David  TShirt    M
Eduard Trouwsers S
'

Indexation

En désavantage de l'utilisation d'un tableau d'objets personnalisés est qu'il est plus lent qu'un tableau d'objets personnalisés. table de hachage qui utilise un algorithme de recherche binaire .
Notez que le avantage l'utilisation d'un tableau d'objets personnalisés permet de rechercher facilement n'importe quoi d'autre, par exemple toutes les personnes qui portent un TShirt avec la taille M :

$arr | Where Article -eq 'TShirt' | Where Size -eq 'M' | Select Name

Pour construire un index de recherche binaire à partir du tableau d'objets :

$h = @{}
$arr | ForEach-Object {
    If (!$h.ContainsKey($_.Name)) { $h[$_.Name] = @{} }
    If (!$h[$_.Name].ContainsKey($_.Article)) { $h[$_.Name][$_.Article] = @{} }
    $h[$_.Name][$_.Article] = $_ # Or: $h[$_.Name][$_.Article]['Size'] = $_.Size
}

$h.david.tshirt.size
M

Note : référençant une clé de table de hachage qui n'existe pas dans Set-StrictMode provoquera une erreur :

Set-StrictMode -Version 2
$h.John.tshirt.size
PropertyNotFoundException: The property 'John' cannot be found on this object. Verify that the property exists.

5voto

Xavier John Points 368

Voici un tableau multidimensionnel simple de chaînes de caractères.

$psarray = @(
 ('Line' ,'One' ),
 ('Line' ,'Two')
)

foreach($item in $psarray)
{
    $item[0]
    $item[1]
}

Sortie :

Line
One
Line
Two

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X