Quelle est la façon idiomatique de découper un tableau par rapport à ses deux extrémités?

La notation de tableau de Powershell a un comportement plutôt bizarre, bien que documenté, pour découper la fin des tableaux. Cette section de la documentation officielle résume assez bien l'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]

Ce commande ne fait pas référence à tous les éléments du tableau, sauf pour le dernier. Il fait référence au premier, au dernier et à l'avant-dernier éléments dans le tableau.

Le code suivant confirme l'bizarrerie:

$a = 0,1,2,3
$a[1..-1]

Qui génère en effet ce résultat bizarre:

1
0
3

Donc, la question Est, Quelle est la façon idiomatique de trancher avec un index relatif le début et un autre relatif la fin du tableau?

Dites-moi que c'est mieux que ce gâchis laid:

$a[1..($a.Count-1)]

Modifier:

Une autre façon de décrire ce que je cherche est la suivante: l'équivalent idiomatique Powershell de cette expression python:

a=1,2,3,4
a[1:-1]

, Qui, bien sûr, évalue (2,3)

28
demandé sur alx9r 2015-02-11 20:07:01

6 réponses

Si vous souhaitez obtenir n éléments à partir de la fin d'un tableau tout simplement chercher les éléments de n pour -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 à la 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 le premier et le dernier indice respectivement. Cependant, dans un PowerShell .. est l'opérateur de plage , 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 récupérer 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 avez besoin d'émuler le comportement de Python, vous devez utiliser 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
28
répondu Ansgar Wiechers 2015-02-11 18:42:35

Bien que pas aussi soigné que vous pourriez vouloir, mais est plus propre dans la façon dont PowerShell fonctionne ...

(@(1,2,3,4)) | Select-Object -Skip 1

Retourne ...

2
3
4
5
répondu John Warde 2017-08-24 11:46:33

Si vous cherchez, disons, les trois premiers et les trois derniers éléments d'un tableau, avec les résultats dans un tableau, un petit ajout de tableau prendra soin du besoin.

[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
2
répondu Dave Bradee 2016-01-18 19:13:34

Cela pourrait être la façon la plus idiomatique de découper un tableau avec ses deux extrémités:

$ Tableau [début..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 retournera 3 4 5 6 7

La valeur de début commence à compter avec zéro, donc une valeur de début de ' 2 ' Vous donne le troisième élément du tableau. La valeur d'arrêt est calculée avec ($A. Length-3), cela supprimera les deux dernières valeurs car $A. Length-3 lui-même est inclus dans la tranche.

J'ai défini $start et $ stop pour plus de clarté, évidemment vous pouvez aussi 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

2
répondu Mathijs303 2017-07-11 12:50:04

Ok, donc c'est moche comme l'enfer mais j'ai trouvé ça [1..99] ou [1..999] fonctionne. Ne pas, cependant, l'utilisation [1..999999] comme PowerShell génère d'abord un tableau de valeurs avant de décider que seuls les cinq premiers comptent, le dernier prend beaucoup de temps pour générer un tableau de millions d'éléments.

C'est génial pour certains scénarios de script, horrible pour le code de production.

1
répondu Bill K 2016-08-16 20:29:11

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)]

En outre, 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)
0
répondu mayursharma 2018-05-01 20:39:33