Рассмотрим коллекцию коллекций и операцию, которую необходимо выполнить внутри конвейера для каждого элемента внутренней коллекции.
Ради простоты, пусть это будет массив массивов, а операция просто выводится на экран. Для представления моего вопроса, давайте также будем иметь массив, элементы которого не являются коллекциями:
$Array = "A", "B", "C"
$ArrayOfArrays = (1, 2, 3), (4, 5, 6), (7, 8, 9)
Мы знаем, что трубопровод разбивает коллекцию на элементы, например:
$Array | & {process {Write-Host $_}}
$ArrayOfArrays | & {process {Write-Host $_}}
Теперь, к моему удивлению, когда я запускаю это, он не разбивает внутренний массив на его элементы:
$ArrayOfArrays | % -process {Write-Host $_}
(1)
и это:
$ArrayOfArrays | % -process {% -process {Write-Host $_}}
(2)
(однако эта последняя может показаться ненужной попыткой, видя, что (1) этого не делает, но я попробовал это ...)
Я ожидал попробовать (1 ), чтобы сделать это, потому что я думал, что трубопровод делает один пробой, и когда элемент получен ForEach-Object
, он будет далее разбивать его, если это коллекция.
Я мог бы решить это только с помощью внутреннего трубопровода:
$ArrayOfArrays | % -process {$_ | % -process {Write-Host $_}}
(3)
, однако с помощью этого подхода я могу исключить ForEach-Object
, конечно:
$ArrayOfArrays | & {process {$_ | & {process {Write-Host $_}}}}
(4)
Итак, мои 2 вопроса:
1 ,
Как получить доступ к элементу коллекции, которая находится в коллекции в конвейере, отличной от try (3) и (4), или это единственный способ сделать это?
2 ,
Если единственный способ сделать то, что задает вопрос 1, - это попытки (3) и (4), тогда что действительный вариант использования ForEach-Object
, где его нельзя устранить? Я имею в виду, что это может быть логичным случаем, но также производительность против блока скрипта Тот факт, что он лучше, чем блок сценариев с одной парой скобок, для меня просто не достаточно ...
.
РЕДАКТИРОВАТЬ после ответа Мануэля Батшинга:
Поскольку ForEach-Object
возвращает элементы коллекции после ее обработки, мы можем сделать это (я позволил go Write-Host, возможно, это была нехорошая произвольная операция, поэтому пусть это будет GetType ):
$ArrayOfArrays | % -process {$_} | & {process {$_.GetType()}}
Но мы также знаем, что если что-то возвращает новый объект в конвейере, это вызовет срыв, если он будет передан дальше и если это коллекция. Таким образом, чтобы выполнить разбивку, мы можем снова исключить ForEach-Object
и сделать это:
$ArrayOfArrays | & {process {$_}} | & {process {$_.GetType()}}
И эту фиктивную операцию можно синтаксически сократить, если я определю фильтр следующим образом:
Filter §
{
param (
[Parameter (Mandatory = $True, ValueFromPipeline = $True)]
[Object]
$ToBeTriggeredForBreakDown
) # end param
$ToBeTriggeredForBreakDown
}
и используйте это так:
$Array | § | & {process {$_.GetType()}}
$ArrayOfArrays | § | & {process {$_.GetType()}}
$ArrayOfArraysOfArrays = ((1, 2), (3, 4)), ((5, 6), (7, 8))
$ArrayOfArraysOfArrays | § | & {process {$_.GetType()}}
$ArrayOfArraysOfArrays | § | § | & {process {$_.GetType()}}
Так что мне все еще трудно увидеть, когда я буду использовать ForEach-Object
, мне кажется, это совершенно бесполезно - за исключением причин, которые я ищу в моем вопросов.
.
РЕДАКТИРОВАТЬ после исследования:
Некоторые коллекции предоставляют свои собственные методы, например, поскольку v4 arrays
имеет метод ForEach
, поэтому, кроме (3 ) и (4), это можно сделать (опять же фиктивная операция, но с меньшим количеством кода):
$ArrayOfArrays.ForEach{$_} | & {process {$_.GetType()}}
, поэтому это частично охватывает вопрос 1.