PowerShell должен возвращать объект [] из канала? - PullRequest
3 голосов
/ 09 марта 2010

С учетом этой функции:

> function Get-ArrayOfArrays() {
    (1,2),(3,4) | % { $_ }
}

Я ожидаю, что возвращаемый тип будет массивом массивов. Однако, похоже, что внутренние массивы расширяются в трубу:

> Get-ArrayOfArrays | % { $_.GetType().Name }
Int32
Int32
Int32
Int32

Фактически, запуск трубы в трубе даст следующие результаты:

> (1,2),(3,4) | % { $_ }
Object[]
Object[]

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

> function Get-ArrayOfArraysWithReturn() {
    (1,2),(3,4) | % { return $_ }
}

> Get-ArrayOfArraysWithReturn | % { $_.GetType().Name }
Object[]
Object[]

Такое поведение выглядит следующим образом: «Если при возврате из функции с не захваченными объектами эти объекты являются массивами, разверните их». Является ли это одним из тех дизайнерских решений «делай то, что полезно». Или я что-то упускаю?

Ответы [ 2 ]

4 голосов
/ 09 марта 2010
(1,2),(3,4) | % {$_}

приводит к выводу вашей функции (1,2) и (3,4) - так же, как эта функция:

function foo { 
    1,2
    3,4 
}

Кикер в том, что каждый из этих массивов снова развернул (сгладил) их содержимое как часть процесса вывода объектов, например ::100100

PS> foo | %{$_.GetType().Name}
Int32
Int32
Int32
Int32

Это похоже на то, что вы видите на хосте при выполнении этого:

PS> 1,2
1
2

Массив развернут таким образом, что отображается каждый элемент массива. Следующее должно делать то, что вы хотите:

function Get-ArrayOfArrays() { 
    (1,2),(3,4)
}

Когда (1,2), (3,4) попадает на выход функции, он развертывается один раз, выводя (1,2) и (3,4). Другой способ, который можно использовать для обхода развертывания коллекции, - это обернуть коллекцию в другую коллекцию из одного элемента с помощью оператора ,, чтобы сохранить форму исходной коллекции, например ::

.
PS> function foo { ,((1,2),(3,4)) }
PS> foo | gtn
Object[]
0 голосов
/ 02 ноября 2012

Я собирался задать аналогичный вопрос, а именно: «Как вы предотвращаете развертывание / объединение / объединение массивов PowerShell?».

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

Например

> (1, 2), (3, 4)
1
2
3
4

Что означает, что он уже был развернут один раз:

[ 1, 2 ] ++ [ 3, 4 ] == [ 1, 2, 3, 4 ] 

Следовательно, то, что печатает переводчик, не обязательно для real вывода кода.

Например, следующий код

1, 2, 3 | ForEach-Object { $_, ($_ * 2) }

берет первые три целых числа и дает нам список из двух чисел [ x, x * 2 ] для каждого. Результат:

[ 1, 2, 2, 4, 3, 6 ]

Однако я хотел следующий вывод:

[ [ 1, 2 ], [ 2, 4 ], [ 3, 6 ] ]

Я использовал оператор запятой ,, как предложил Кит Хилл:

$list = 1, 2, 3 | ForEach-Object { , ($_, ($_ * 2)) }

Так как мы возвращаем массив, массив, int для каждого входа:

1   -> [ [ 1, 2 ] ]
2   -> [ [ 2, 4 ] ]    
3   -> [ [ 3, 6 ] ] 

Мы ожидаем, что он будет развернут только один раз, так что $list будет равен:

[ [ 1, 2 ] ] + [ [ 2, 4 ] ] + [ [ 3, 6 ] ] == [ [ 1, 2 ], [ 2, 4 ], [ 3, 6 ] ]

И мы можем проверить, что это

> $list[0]   #  get first element of list, should be [ 1, 2 ]
1
2
> $list[2][1]  # from the third elem, [ 3, 6 ], get 2nd elem, should be 6
6

Однако, когда переводчик печатает список, он развертывает его еще раз:

[ 1, 2 ] ++ [ 2, 4 ] ++ [ 3, 6 ] == [ 1, 2, 2, 4, 3, 6 ]

так мы получаем

> $list
# prints [ 1, 2, 2, 4, 3, 6 ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...