Петля Powershell | Перемещение файлов и создание ярлыков [дубликатов]

Мое обходное решение:

function add(a, b, precision) {
    var x = Math.pow(10, precision || 2);
    return (Math.round(a * x) + Math.round(b * x)) / x;
}

precision относится к числу цифр, которые вы хотите сохранить после десятичной точки во время добавления.

91
задан Peter Mortensen 8 February 2016 в 13:10
поделиться

3 ответа

Я думаю, вы могли бы использовать параметр ExpandProperty в Select-Object.

Например, чтобы получить список текущего каталога и просто отобразить свойство Name, следующее:

ls | select -Property Name

Это все еще возвращает объекты DirectoryInfo или FileInfo. Вы всегда можете проверить тип, проходящий через трубопровод, по трубопроводу до Get-Member (псевдоним gm).

ls | select -Property Name | gm

Итак, чтобы развернуть объект должен быть типом свойства, которое вы ищете, вы можете сделать следующее:

ls | select -ExpandProperty Name

В вашем случае вы можете просто сделать следующее, чтобы переменная была массивом строк, где строки являются свойством Name:

$objects = ls | select -ExpandProperty Name
158
ответ дан Peter Mortensen 1 September 2018 в 08:14
поделиться

В дополнение к ранее имеющимся полезным ответам с указанием того, когда использовать этот подход и сравнение производительности.

  • Вне конвейера используйте:
    $objects.Name
    (PSv3 +), как показано в ответе rageandqq , который синтаксически проще и намного быстрее. Доступ к свойству на уровне коллекции для получения значений членов в качестве массива называется перечислением членов и является функция PSv3 + ; В качестве альтернативы, в PSv2 используйте инструкцию foreach , выход которой вы также можете назначить непосредственно переменной:
    $results = foreach ($obj in $objects) { $obj.Name }
    Компромиссы: как входной массив сбора, так и выходной массив должны вписываться в память как целое . Если входная коллекция сама является результатом команды (конвейера) (например, (Get-ChildItem).Name), команда должна сначала выполняться до завершения до того, как к элементам результирующего массива можно получить доступ.
  • В конвейере , где результат должен быть обработан дальше или результаты не помещаются в память в целом, используйте:
    $objects | Select-Object -ExpandProperty Name
    . Необходимость в -ExpandProperty объясняется в ответ Скотта Саада . Вы получаете обычные преимущества конвейера от обработки по одному, что, как правило, дает выход сразу и сохраняет постоянство памяти (если вы в конечном итоге не собираете результаты в памяти). Компромисс: использование трубопровода сравнительно медленно .

Для коллекций ввода small (массивов) вы, вероятно, не заметите разницы и, особенно в командной строке, иногда можете ввести команду легко.


Вот простая альтернатива, которая, однако, является самым медленным ; он использует упрощенный синтаксис

$objects | Select-Object -ExpandProperty Name
, называемый оператором (опять же, 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 ) это решение на уровне с перечислением члена (хотя последний синтаксически проще).
  • Вариант script-block , хотя и намного медленнее, допускает произвольные преобразования ; это более быстрый вариант «все-в-памяти-в-одном», альтернативный командному коду 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
  • Член-перечисление / [20] Решение foreach работает примерно на 2,5 медленнее, чем на самом деле, но все же примерно в 4-5 раз быстрее, чем самое быстрое решение для трубопровода.
  • Использование блока сценария с решением метода сбора (.ForEach({ ... }) резко замедляет работу, так что он практически совпадает с самым быстрым решением на основе трубопровода (Select-Object -ExpandProperty).
  • % Number (ForEach-Object Number), любопытно, выполняет худшее, хотя % Number является концептуальным эквивалентом % { $_.Number }).

Исходный код для тестов:

Примечание. Загрузите функцию Time-Command из этого 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
7
ответ дан mklement0 1 September 2018 в 08:14
поделиться

В качестве еще более простого решения вы можете просто использовать:

$results = $objects.Name

Который должен заполнить $results массивом всех значений свойств «Имя» элементов в $objects.

49
ответ дан rageandqq 1 September 2018 в 08:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: