Полезный ответ Андрея Одегова предлагает PowerShell-идиоматическое решение, которое также демонстрирует упрощенный основанный на аргументах синтаксис Where-Object
, называемый оператор сравнения , представленный в PSv3.
В PSv4 + есть еще один вариант, использующий * оператор '1008 *.Where()
и .ForEach()
коллекции методы , которые работают лучше;однако обратите внимание, что для этого требуется, чтобы входная коллекция находилась в памяти полностью [1] (что здесь имеет место):
$data.Where({ $_.name -eq "Item2" }).ForEach({ $_.stock -= 1 })
Или, если вы знаете, что будет толькобыть one match, проще:
$data.Where({ $_.name -eq "Item2" })[0].stock -= 1
Также обратите внимание, как используется -eq
вместо -contains
, потому что $_.name
является скаляром (одно значение), а не коллекция , а -contains
предназначена для коллекций.
Что касается то, что вы пытались :
Похоже, вы пытались применить что-то похожее на понимание списка в стиле Python, которое PowerShell не поддерживает.
Вместо этого вы должны начать со всей коллекции, отфильтровать ее, а затем применить требуемыйоперация над результирующими элементами, как показано.
Я пробовал с этим:
$data.stock = $data.stock - 1 | Where-Object name -contains "item2"
В PSv3 +, доступ к свойству в коллекции возвращает массив ([System.Object[]]
) значений свойств, собранных из элементов коллекции .
Следовательно, с вашими примерами данных $data.stock - 1
является эквивалентом:
(10, 10, 10) - 1 # !! BROKEN: arrays don't support the "-" operator
Поскольку массивы не поддерживают оператор -
(реализация которого основана на статическомop_Subtraction
метод), вы получили сообщение об ошибке, которое вы видели.
[1] Конвейер PowerShell и обработка всего в памяти :
Использование конвейера является относительно медленным, но ограничивает память, что позволяет обрабатывать коллекции, которые не помещаются в память в целом ;Например:
ConvertFrom-Csv in.csv | Where-Object ... | ForEach-Object ... | Export-Csv out.csv
В приведенном выше примере каждая строка из in.csv
обрабатывается индивидуально и отправляется по конвейеру сразу , и Export-Csv
создаетвывод строка за строкой .
Таким образом, нет необходимости считывать ввод в память в целом .
В отличие от этого,если выполнить обработку коллекции с помощью (с учетом массива) операторов / .Where()/.ForEach()
методов / a foreach
loop , вы получите более высокую производительность, но входные данные должны быть собраны в памяти полностью, заранее , что не всегда является опцией.
См. нижнюю часть этого ответа моего отчета о том, как сравниваются подходыс точки зрения производительности (скорость исполнения).