La notation de tableau de Powershell a un comportement plutôt bizarre, bien que documenté, pour couper la fin des tableaux. Cette section de la documentation officielle résume assez bien la bizarrerie:
Les nombres négatifs comptent à partir de la fin du tableau. Par exemple, "-1" fait référence au dernier élément du tableau. Pour afficher les trois derniers éléments du tableau, tapez:
$a[-3..-1]
Cependant, soyez prudent lorsque vous utilisez cette notation.
$a[0..-2]
Cette commande ne fait pas référence à tous les éléments du tableau, à l'exception du dernier. Il fait référence au premier, au dernier et à l'avant dernier élément du tableau.
Le code suivant confirme la bizarrerie:
$a = 0,1,2,3
$a[1..-1]
Ce qui en effet produit ce résultat bizarre:
1
0
3
La question est donc de savoir ce que is est le moyen idiomatique de découper avec un index relatif le début et un autre relatif la fin du tableau.
S'il te plaît, dis-moi que c'est quelque chose de mieux que ce sale bazar
$a[1..($a.Count-1)]
Modifier:
Une autre façon de décrire ce que je recherche est la suivante: L’équivalent idiomatique de Powershell de cette expression python:
a=1,2,3,4
a[1:-1]
Ce qui, bien sûr, est évalué à (2,3)
Si vous voulez obtenir les éléments n à la fin d'un tableau, récupérez simplement les éléments de -n à -1:
PS C:\>$a = 0,1,2,3
PS C:\>$n = 2
PS C:\>$a[-$n..-1]
2
3
Edit: PowerShell ne prend pas en charge l'indexation par rapport au début et fin du tableau, en raison du fonctionnement de $a[$i..$j]
. Dans une expression Python a[i:j]
, vous spécifiez i
et j
comme premier et dernier index, respectivement. Cependant, dans un PowerShell ..
est l'opérateur intervalle , qui génère une séquence de nombres. Dans une expression $a[$i..$j]
, l'interpréteur évalue d'abord $i..$j
à une liste d'entiers, puis la liste est utilisée pour extraire les éléments du tableau sur ces index:
PS C:\>$a = 0,1,2,3
PS C:\>$i = 1; $j = -1
PS C:\>$index = $i..$j
PS C:\>$index
1
0
-1
PS C:\>$a[$index]
1
0
3
Si vous devez émuler le comportement de Python, vous utilisez doit une sous-expression:
PS C:\>$a = 0,1,2,3
PS C:\>$i = 1; $j = -1
PS C:\>$a[$i..($a.Length+$j-1)]
1
2
Bien que ce ne soit pas aussi élégant que vous le voudriez, il est plus propre dans le fonctionnement de PowerShell ...
(@(1,2,3,4)) | Select-Object -Skip 1
résultats ...
2
3
4
Cela pourrait être le moyen le plus idiomatique de découper un tableau avec ses deux extrémités:
$ array [start..stop] où stop est défini en prenant la longueur du tableau moins une valeur à décaler de la fin du tableau:
$a = 1,2,3,4,5,6,7,8,9
$start = 2
$stop = $a.Length-3
$a[$start..$stop]
Cela reviendra 3 4 5 6 7
La valeur initiale commence à compter avec zéro, de sorte qu'une valeur initiale de '2' vous donne le troisième élément du tableau. La valeur d'arrêt est calculée avec ($ a.Length-3). Les deux dernières valeurs seront supprimées car $ a.Length-3 est inclus dans la tranche.
J'ai défini $ start et $ stop pour plus de clarté, vous pouvez évidemment l'écrire comme ceci:
$a = 1,2,3,4,5,6,7,8,9
$a[2..($a.Length-3)]
Cela retournera également 3 4 5 6 7
Si vous recherchez, par exemple, les trois premiers et les trois derniers éléments d'un tableau, avec les résultats dans un tableau, un petit ajout de tableau répondra aux besoins.
[array]$A = (([int][char]'A')..([int][char]'Z')) | ForEach-Object {[char]$_}
$B = $A[0..2]+$A[-3..-1]
Clear-Host
Write-Host "Original List"
Write-Host $A -NoNewline -Separator ', '
Write-Host
Write-Host "First three and last three"
Write-Host $B -NoNewline -Separator ', '
Rendements:
Original List
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
First three and last three
A, B, C, X, Y, Z
Ok, donc c'est moche, mais j'ai trouvé que [1..99] ou [1..999] fonctionnait. Cependant, n'utilisez pas [1..999999] car PowerShell génère d'abord un tableau de valeurs avant de décider que seuls les cinq premiers importent, le dernier prend beaucoup de temps pour générer préalablement un tableau de millions d'éléments.
C'est très bien pour certains scénarios de script, horrible pour le code de production.
Je crois que c'est la bonne façon de le faire. toutes les autres méthodes nécessitent plus de code.
$a[1..($a.Count-1)]
De plus, si le tableau est converti en chaîne, il devient facile d'obtenir des données comme ci-dessous:
$a = 0,1,2,3
[string]::Concat($a).Substring(1)