В дополнение к уже существующим, полезным ответам с указанием , когда использовать, какой подход и сравнение производительности .
Для небольших входных коллекций (массивов) вы, вероятно, не заметите разницу , и, особенно в командной строке, иногда легче набрать команду важно.
Вот простая в вводе альтернатива , которая, однако, является самым медленным подходом ; он использует упрощенный синтаксис ForEach-Object
, называемый оператором операции (опять же, PSv3 +):
; например, следующее решение PSv3 + легко добавить к существующей команде:
$objects | % Name # short for: $objects | ForEach-Object -Process { $_.Name }
Ради полноты: малоизвестный PSv4 + .ForEach()
метод сбора - еще одна альтернатива :
# By property name (string):
$objects.ForEach('Name')
# By script block (much slower):
$objects.ForEach({ $_.Name })
Этот подход аналогичен перечислению членов , с теми же компромиссами, за исключением того, что конвейерная логика не применяется; это немного медленнее , хотя все же заметно быстрее, чем конвейер.
Для извлечения единственного значения свойства по name ( string аргумент) это решение наравне с перечислением членов (хотя последнее синтаксически проще).
Блок сценариев вариант , хотя и намного медленнее, допускает произвольные преобразования ; это быстрее - все в оперативной памяти - альтернатива командлету ForEach-Object
командлет .
Сравнение производительности различных подходов
Вот выборочных таймингов для различных подходов, основанных на наборе входных данных 100,000
объектов , усредненных по 100 прогонам; абсолютные числа не важны и варьируются в зависимости от многих факторов, но они должны дать вам представление о относительной производительности:
Command FriendlySecs (100-run avg.) Factor
------- --------------------------- ------
$objects.ForEach('Number') 0.078 1.00
$objects.Number 0.079 1.02
foreach($o in $objects) { $o.Number } 0.188 2.42
$objects | Select-Object -ExpandProperty Number 0.881 11.36
$objects.ForEach({ $_.Number }) 0.925 11.93
$objects | % { $_.Number } 1.564 20.16
$objects | % Number 2.974 38.35
Решение с использованием метода сбора данных, основанного на перечислении элементов / свойствах, быстрее в 10 раз быстрее, чем самое быстрое решение на основе конвейера.
Решение foreach
работает примерно в 2,5 раза медленнее, но все же примерно в 4-5 раз быстрее, чем самое быстрое конвейерное решение.
Использование блока сценариев с решением для метода сбора данных (.ForEach({ ... }
) значительно замедляет работу, так что он практически соответствует быстрейшему конвейерному решению (* 1192) *).
% Number
(ForEach-Object Number
), что любопытно, работает хуже, хотя % Number
является концептуальным эквивалентом % { $_.Number }
).
Исходный код для тестов :
Примечание. Для запуска этих тестов загрузите функцию Time-Command
из this Gist .
$count = 1e5 # input-object count (100,000)
$runs = 100 # number of runs to average
# Create sample input objects.
$objects = 1..$count | % { [pscustomobject] @{ Number = $_ } }
# An array of script blocks with the various approaches.
$approaches = { $objects | Select-Object -ExpandProperty Number },
{ $objects | % Number },
{ $objects | % { $_.Number } },
{ $objects.ForEach('Number') },
{ $objects.ForEach({ $_.Number }) },
{ $objects.Number },
{ foreach($o in $objects) { $o.Number } }
# Time the approaches and sort them by execution time (fastest first):
Time-Command $approaches -Count $runs | Select Command, FriendlySecs*, Factor