Подтвердить что ты не робот

Каков идиоматический способ срезания массива относительно обоих его концов?

Обозначение массива Powershell имеет довольно причудливое, хотя и документированное поведение для отсечения конца массивов. В этом разделе из официальная документация достаточно хорошо подсвечивает причудливость:

Отрицательные числа подсчитываются с конца массива. Например, "-1" относится к последнему элементу массива. Чтобы отобразить последние три элементы массива, тип:

$a[-3..-1]

Однако будьте осторожны при использовании этих обозначений.

$a[0..-2]

Эта команда не относится ко всем элементам массива, кроме для последнего. Это относится к первому, последнему и второму последнему элементов в массиве.

Следующий код подтверждает причудливость:

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

Что действительно выводит этот причудливый результат:

1
0
3

Итак, вопрос в том, каков идиоматический способ срезания с одним индексом относительно начала и другого относительного конца массива?

Скажите, пожалуйста, что-то лучше, чем этот уродливый беспорядок:

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

Edit:

Другим способом описания того, что я ищу, является следующее: Идиоматический эквивалент Powershell этого выражения python:

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

Что, конечно, оценивается как (2,3)

4b9b3361

Ответ 1

Если вы хотите получить n элементов из конца массива, просто извлеките элементы из -n в -1:

PS C:\> $a = 0,1,2,3
PS C:\> $n = 2
PS C:\> $a[-$n..-1]
2
3

Редактировать: PowerShell не поддерживает индексирование относительно начала и конца массива из-за способа работы $a[$i..$j]. В выражении Python a[i:j] вы указываете i и j как первый и последний индекс соответственно. Тем не менее, в PowerShell .. это оператор диапазона, который генерирует последовательность чисел. В выражении $a[$i..$j] интерпретатор сначала оценивает $i..$j в список целых чисел, а затем этот список используется для извлечения элементов массива по этим индексам:

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

Если вам нужно эмулировать поведение Python, вы должны использовать подвыражение:

PS C:\> $a = 0,1,2,3
PS C:\> $i = 1; $j = -1
PS C:\> $a[$i..($a.Length+$j-1)]
1
2

Ответ 2

Хотя не такой аккуратный, как вы могли бы хотеть, но более чистым в том, как работает PowerShell...

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

возвращает...

2
3
4

Ответ 3

Это может быть самый идиоматический способ среза массива с обоими его концами:

$array [start..stop], где stop определяется путем принятия длины массива минус значение для смещения от конца массива:

$a = 1,2,3,4,5,6,7,8,9
$start = 2
$stop = $a.Length-3
$a[$start..$stop]

Это вернет 3 4 5 6 7

Начальное значение начинается с нуля, поэтому начальное значение "2" дает вам третий элемент массива. Стоп-значение рассчитывается с помощью ($ a.Length-3), это приведет к отбрасыванию последних двух значений, потому что сам объект $a.Length-3 включен в срез.

Я определил $start и $stop для ясности, очевидно, вы также можете написать это следующим образом:

$a = 1,2,3,4,5,6,7,8,9
$a[2..($a.Length-3)]

Это также вернет 3 4 5 6 7

Ответ 4

Если вы ищете, скажем, первые три и последние три элемента в массиве, с результатами в массиве, небольшое дополнение массива позаботится о необходимости.

[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 ', '

Урожайность:

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

Ответ 5

Хорошо, так что это уродливо, но я обнаружил, что работает [1.99] или [1.999]. Однако не используйте [1..999999], так как PowerShell сначала генерирует массив значений, прежде чем решить, что только первые пять вопросов, последнее занимает значительное время, чтобы предварительно создать миллионный массив элементов.

Это отлично подходит для определенных сценариев сценариев, ужасных для производственного кода.

Ответ 6

Я считаю, что это правильный способ сделать это. все другие методы требуют больше кода.

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

Кроме того, если массив преобразуется в строку, становится легко получить данные, как показано ниже:

$a = 0,1,2,3
[string]::Concat($a).Substring(1)

Ответ 7

$ arr = @(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

$arr | Select-Object -First 5 | Select-Object -Index (@(0..4) | Where-Object { $_ % 2 -eq 0}) 
$arr | Select-Object -Last 5
$arr | Select-Object -Unique
$arr | Sort-Object | Select-Object -Unique
$arr | Where-Object {  $_ % 5 -eq 0 } | Sort-Object | Select-Object -Unique
$arr | Select-Object -First ($arr.Count - 3)

На самом деле код говорит сам за себя. Мне событие не нужно объяснять.

Тем не мение, 1) Предоставьте первые пять элементов, но каждую секунду из этих пяти. Равен arr [: 5: 2] в Python 2) Получить последние пять элементов. 3) Дает уникальные элементы 4) Сначала отсортируйте, а затем предоставьте уникальный 5) Дает только элементы, которые равны 0, применяя по модулю 5, sort, unique. 5) Укажите первое количество элементов в этом массиве минус только три элемента.