Какие общие советы у вас есть для игры в гольф в Windows PowerShell? Я ищу идеи, которые могут быть применены к проблемам с гольф-кодом в целом, которые, по крайней мере, несколько специфичны для PowerShell (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.
- почти дословно взято из вопроса Марко .
code-golf
tips
powershell
детеныш
источник
источник
Ответы:
Полномочия 10 литералов с научными обозначениями:
Полномочия 2 литералов:
Может пригодиться.
источник
Если вам нужно запустить цикл, и вы точно знаете , сколько раз он должен запускаться каждый раз, рассмотрите возможность передачи массива непрерывных целых чисел
ForEach-Object
через%
псевдоним вместо использованияfor
.for($x=1;$x-le10;$x++){
...}
против
1..10|%{
...}
источник
Вы можете пропустить много пробелов в PowerShell. Если кажется, что в этом нет необходимости, это вполне возможно. Это особенно полезно при сравнении.
Пример:
против
Если вам нужно разветвить свой сценарий на основе результатов одного теста, который может иметь несколько результатов,
switch
иногда можно сопоставить или превзойти оператор if.Пример (переключатель против if / else - tie):
против
Или (переключение против if / elseif / else - переключение выигрывает на 15):
против
Если на самом деле переключатель основан на определенных математических результатах, как, например, приведенная выше операция по модулю, вы можете полностью заменить переключатель на массив. Здесь он сохраняет еще 13 символов и даже короче, чем исходный оператор с двумя вариантами if / else. (Спасибо Данко Дурбику за это.)
Если вы будете часто использовать определенную команду, особенно без существующего сокращенного псевдонима, настройте односимвольный псевдоним на ранней стадии.
Пример:
против
источник
('even','odd')[$x%2]
FYI.Инкапсуляция команды, которая определяет переменную в скобках, позволяет передавать определение переменной непосредственно другим командам.
Например, вы можете установить $ x, а затем установить $ y на основе значения $ x за один выстрел с помощью этого:
Вместо этого:
Вы можете установить $ h и вывести его так:
Вместо этого:
источник
($x=New-Object Windows.Forms.Form).Controls.Add($t)
Переключатель может действовать как цикл, если ему дан массив. Например:
Будет выводить:
Я не совсем уверен, где это будет полезно, но я ожидаю, что это когда-нибудь пригодится.
источник
ForEach-Object
иswitch
внутри этого. Это, например, (в реальном мире) код, очень подходящий для написания быстрых парсеров текстовых файлов, где вам нужно делать разные вещи в зависимости от того, какое регулярное выражение соответствует строке.switch -File $path
дляЗаменить
[math]::pow
умножением. Вместо тоготы можешь написать
Это работает для целочисленных показателей> = 0.
источник
iex
... Псевдоним дляInvoke-Expression
Операторы сравнения работают с коллекциями значений, возвращая совпадающие значения:
даст
3
,4
а5
. В некоторых случаях это может помочь сохранить в противном случае дольше|?{$_...}
.-match
тоже оператор сравнения.источник
1..5-gt2
Используйте псевдонимы, когда это возможно. Есть куча полезных:
источник
Хотите найти максимум или минимум коллекции значений? Пытался
или
уже?
Просто отсортируйте и используйте последний или первый элемент:
источник
0
,1
,2
,3
,4
,5
,6
,7
,8
или9
, было бы сохранить байт записать известную длину вместо-1
.Сокращение названий свойств
К сожалению, в отличие от параметров, свойства / методы (все, что доступно с помощью точки
.
) обычно не могут быть сокращены до однозначной формы.Но некоторые командлеты могут работать на именах свойств и принимать групповые символы, и есть малоизвестные наборы параметров из
%
и?
которые могут быть полезны.Обычно мы передаем блок скриптов и обращаемся к элементу с помощью
$_
, но есть другая форма, которая принимает имя свойства и принимает подстановочный знак.С таким свойством, как
.Length
мы, мы не можем использовать магию v3, которая обычно работала бы с массивом, потому чтоLength
это свойство самого массива, поэтому вышеупомянутые два могут использоваться для получения длин отдельных членов.select
Приходит немного короче.Но
%
может взять имя свойства напрямую и вернуть это значение:Который может быть сокращен с подстановочными знаками. Подстановочный знак должен разрешаться в одном свойстве (или методе, подробнее об этом позже), поэтому он выдаст полезную ошибку, если этого не произойдет, с указанием, к каким именно членам он может разрешить.
В случае
Length
,Le*
как правило, самый короткий. Даже для одной строки этот метод на 1 байт короче, чем просто использование свойства.Но в зависимости от того, что вы делаете с этим, это может быть хуже. Вы можете сделать это,
$a.Length*5
но сделать это с конвейерным выражением, вам нужно будет обернуть его($a|% Le*)*5
; может все еще стоить, если он против массива, но дело в том, что это не всегда уместно в качестве прямой замены.Он работает и с методами, и вы можете не
()
указывать полное имя, которое имеет ту же длину, но те же ограничения, что и выше, о необходимости иногда оборачивать его.Метод должен иметь перегрузку, которая не принимает параметров(вы можете передавать аргументы, помещая их после имени метода, что очень приятно):С аргументами:
Это не совсем то же самое, что
-replace
оператор выполняет замену регулярных выражений, но если вы просто заменяете строку, использование (сейчас) может быть короче, если использовать метод; помогает то, что строки являются аргументами командлета, а не аргументами метода, поэтому их не нужно заключать в кавычки.Свойства где-объекта
?
также может принимать (частичные) имена свойств и применять к ним «оператор» (в форме параметров переключателя). Опять же, это может быть короче, чем использование стандартногоWhere-Object
подхода к блоку сценариев, если имя свойства достаточно длинное и уникальное.источник
.ToString()
!Нахождение суммы долгий путь:
Более короткий путь:
И еще короче
источник
Точки с запятой и разрывы строк взаимозаменяемы. Гольф-код часто более читабелен, если не заключать его в одну строку. И длина все та же (при условии, что вы используете U + 000A в качестве разрыва строки, который PowerShell обрабатывает без проблем).
источник
Get
Глагол подразумевается. Это может сократить любойGet-Frob
до всегоFrob
. Частыми претендентами являютсяdate
илиrandom
.Обратите внимание, что в некоторых случаях это не будет работать должным образом, поскольку в вашем пути могут быть утилиты GNU (или другие собственные программы, которые конфликтуют). Порядок поиска команд в этом случае, похоже, предпочитает нативную программу, прежде чем она рассматривает командлеты с
Get-
удаленными:источник
nal g Get-Random
сохранения символов позже. Изменение егоnal g Random
приводит к зависанию сценария на неопределенное время (или, по крайней мере, занимает слишком много времени для обработки - у меня не хватило терпения дождаться его завершения, но это занимает на несколько порядков больше, чем в исходной форме) прежде чем я прерву).Measure-Command
вызова (100 разGet-Random
противrandom
) говорят мне, что это примерно в 500 раз медленнее. Я не знал этого раньше, если честно. Но хорошо иметь это в виду, особенно в циклах со многими итерациями. Это , как говорится, golfed код должен быть коротким, не быстро ( что , как говорится, это отстой придется ждать два дня для ответа на задачи проекта Эйлера).Get-Variable
vs.gv
и получил подобное сравнение.Get-
. Это довольно мрачное раздувание во время выполнения для экономии всего 4 символов в длину.for
Циклы могут содержать от 0 до 3 операторов в заголовке:Бесконечный цикл:
Цикл с инициализацией:
Цикл с инициализацией и конечным условием:
В таких случаях дополнительные точки с запятой в конце могут быть опущены (это явно указано в спецификации языка , поэтому это не детали реализации) в отличие от языков, подобных C, которые всегда требуют ровно три оператора.
Это также делает
while
немного короче. сравнитьа также
С добавленным бонусом, который вы можете вставить в предыдущую строку (если она есть) в
for
также без дополнительных затрат (и даже сохранение персонажа).источник
Если вы назначаете массив, который, как вы знаете, будет иметь только два значения, не используйте индексацию.
Что-то вроде этого:
Можно легко превратить в это:
Это также может быть полезно, если вам нужен только первый элемент массива:
источник
$a="apple";$o="orange"
одинаковы по длине. Это более длинные массивы, которые иногда можно довольно хорошо оптимизировать, например, путем помещения всех элементов в строку с разделителем и последующего использования-split
(лучше всего использовать пробел в качестве разделителя, потому что тогда унарного-split
будет достаточно).Приведение к строке:
против
Приведение к строке также можно использовать для выравнивания массива строк, вместо того, чтобы присоединять его:
против
Приведение строки к числовому типу:
против
Также очень полезно знать, что PowerShell всегда использует тип левого операнда для определения окончательного типа выражения и применяемых преобразований:
который может помочь определить, где ненужные броски.
источник
Не забывайте, что вам не всегда нужно указывать полное имя параметра, а некоторые параметры являются позиционными.
... можно обрезать до ...
... потому что "I" в этом случае достаточно, чтобы однозначно определить
InputObject
из других допустимых параметров для этой команды.Вы можете обрезать его дальше, чтобы ...
... потому что
InputObject
это позиционный параметр.Трубопровод обычно короче подачи объектов в качестве параметра, особенно когда он может устранить необходимость в скобках. Давайте подрежем наш генератор случайных чисел дальше ...
Также ищите другие способы выполнить то же самое, даже если вы не можете изменить команду. Для приведенного выше случая вы можете сделать это:
Или, включив другое предложение *:
** Примечание. Отказ
Get-
от имени команды может увеличить время выполнения примерно на 50 000%. Неплохо, если вам нужна команда только один раз, но будьте осторожны при ее использовании в длинных циклах. *И вот как можно сбить простую команду до трети ее размера.
источник
Поддельный троичный оператор. Вы можете назначить прямо из
if
заявления:Но вы можете использовать 2-элементный массив и использовать тест для индексации в нем. Результаты $ falsey получают элемент 0, результаты $ truey принимают элемент 1:
NB. что это действительно выполняет индексацию массива, и если в результате теста будет получено значение, которое может быть преобразовано в целое число, вы запросите элемент за пределами массива и получите $ null обратно, и вам нужно будет выполнить
!(test)
принудительное принудительное приведите результат к типу bool с обратными параметрами.источник
$()
. Существовало различие в использовании конвейеров из команд и операторов в качестве выражений. Кажется, что это уже прошло, по крайней мере, в PowerShell 5.При использовании числа в качестве аргумента оператора, который в противном случае потребовал бы строку, вы можете использовать число напрямую. сравнить
против
Работает
-split
также. Аргумент всегда сначала преобразуется в строку.источник
-replace
также.-replace
также работает без второго аргумента, если вы хотите удалить совпадения,Абсолютная величина
С
Вместо того
использование
Конечно, сбережения отменяются, если нужны скобки.
источник
Если вам нужно замолчать ошибки, очевидным вариантом будет
Однако это слишком долго. Более короткий вариант - запустить
try
блок как блок скрипта и просто перенаправить ошибки в неустановленную переменную ($null
будет обычной, но это все еще слишком долго):Это экономит пять ценных байтов (если не мир).
источник
Используйте
$ofs
специальную переменную для изменения вывода utput F IELD S eparator используется , когда stringifying массив. Полезно, если вам нужно преобразовывать массивы в строки несколько раз.Например:
Сохраняет 2+ n символов на втором
-join
, где n - длина разделителя, и сохраняет дополнительные 5+ n для третьего-join
и каждого последующего.источник
Автоматические переменные имеет булевы для истинного и ложного , как
$true
и$false
но вы можете получить аналогичные результаты с использованием логического оператора не!
и целых чисел 0 и 1 (или любое ненулевого числа.)Почти все выражения PowerShell могут быть оценены как логические. Поэтому, если вы знаете, как оцениваются определенные данные, вы можете получить логические значения и вам никогда не потребуется явно приводить их. Помните о значении LHS при этом.
Есть и другие примеры, но вы можете легко проверить, выполнив приведение
источник
$null
неинициализированные переменные имеют значение false. Пустая строка (и переменные, установленные в пустую строку), являются ложными. И т. Д. Затем его можно использовать для быстрого индексирования в массив (например, при выполненииif
/else
), как это было использовано в FizzBuzz .int
s просто корочеbool
. Вы можете использовать0
и1
так же хорошо. В этом отношении очень помогают неявные преобразования (которые вы можете часто вызывать с помощью определенных операторов).Invoke-Expression
иGet-Random
может также получить вход конвейера вместо аргументов.Для
iex
этого позволяет сохранить скобки на некоторых выражениях:В
random
этом случае можно немного оптимизировать общий случай:Последний способ его использования просто выбирает элемент из списка.
-c
Аргумент может быть дано , чтобы позволить более одного выбора.источник
Рассмотрите возможность хранения повторяющихся блоков сценариев в переменных вместо использования функций.
Я собирался использовать это, чтобы сохранить некоторые символы в моей реализации Rock, Paper, Scissors, прежде чем понял, что перезапись функции как переменной делает ненужной даже переменную. Тем не менее, это может быть полезно для других скриптов, когда вы на самом деле выполняете один и тот же код несколько раз.
против
источник
params(...)
он занял бы больше места, чем экономит определение функции. Связанный: Использованиеfilter
более ,function
когда вы можете сделать это.$args
чтобы избежать необходимостиparams
; то есть$x={$args[0]+2}
(или даже$x={2+"$args"}
); может сохранить символ или 2 в некоторых обстоятельствах. Вы также можете комбинировать это с другим трюком для нескольких параметров:$x={$a,$b=$args;$a+$b+3}
$s|% t*y
Вместо этого вы можете использовать[char[]]$s
для разделения строки на массив символов. Исходя из ответа Тесселлатинга Хеклера :% t*y
расширяется до| ForEach-Object -Method ToCharArray
экв. из"$args".ToCharArray()
Например, сравнить
а также
а также
Это полезно с
$args
особенно:$args|% t*y
источник
%
трюк для участников несколько раз, но большинство моих игр в гольф предшествуют этой особенности ;-). Это довольно общая техника: попробуйте найти комбинацию букв / подстановочных знаков, которая соответствует нужному вам свойству / методу (и короче реальной).$s|% *per
за$s.toUpper()
и$s|% *wer
за$s.toLower()
. Я согласен, это довольно опрятно.|% t* "ddd\:hh\:mm\:ss"
для[TimeSpan].toString("ddd\:hh\:mm\:ss")
Используйте логическую логику вместо счетчиков if в цикле
Предположим, вы добавляете все четные числа от 1 до 10 ...
2+4+6+8+10=30
Вы можете использовать логическое отрицание, чтобы сократить его до
чтобы сохранить байт, но как же вместо этого использовать неявное приведение логических значений к целым, и бросить условное в аккумулятор
Сохраняет 6 байтов в этом примере.
источник
Преобразование чисел с плавающей запятой в целые числа в PowerShell является чем-то вроде минного поля. По умолчанию при конвертации выполняется округление Bankers, которое не всегда обрезает десятичную дробь и оставляет меньшее целое число, или всегда округляет .5 до следующего числа, как это делают люди случайно, оно округляет четные в одну сторону и увеличивает коэффициент в другую - это может быть удивительным, например
и нарушить вычисления Codegolf. Многие другие распространенные языки делают округление, поэтому вопросы о гольфе часто требуют усечения. Вы можете достичь
[Math]::Floor()
следующей лучшей вещи, но остерегайтесь, это ведет себя так же, как усечение для положительных чисел, но отрицательные числа снимаются ниже - дальше от нуля.[Math]::Truncate()
это то, что вам нужно, чтобы привести поведение PS в соответствие с округлением по умолчанию на другом языке, но это много символов.Замена регулярных выражений после десятичной точки может помочь сохранить пару символов:
источник
Реверсивный массив
Пригодится во многих задачах ascii-art, где результат отражается каким-то образом.
Предположим, у вас есть
Традиционный метод обращения является длинным, скучным и не оставляет массив в конвейере для немедленного использования.
Индексирование непосредственно в массив в обратном порядке экономит несколько байтов, поскольку оставляет результаты в конвейере, но все еще довольно долго:
Вместо этого попробуйте цикл
источник
Начиная с PowerShell Core 6, вы также можете использовать диапазоны для символов:
который может заменить гораздо более громоздкий
источник
[char[]](65..90)
это также удобный способ для создания алфавита