Jakie masz ogólne wskazówki dotyczące gry w golfa w Windows PowerShell? Szukam pomysłów, które można zastosować do ogólnych problemów z kodowaniem golfa, które są przynajmniej nieco specyficzne dla PowerShell (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.
- wziął prawie dosłownie pytanie marcoga .
code-golf
tips
powershell
Joey
źródło
źródło
Odpowiedzi:
Potęgi 10 literałów z notacją naukową:
Potęgi 2 literałów:
Może się przydać.
źródło
Jeśli potrzebujesz uruchomić pętlę i wiesz dokładnie, ile razy musi ona działać za każdym razem, rozważ użycie pipety do tablicy ciągłych liczb całkowitych
ForEach-Object
za pośrednictwem%
aliasu zamiast używaniafor
.for($x=1;$x-le10;$x++){
...}
vs
1..10|%{
...}
źródło
Można pominąć spacje dużo w PowerShell. Jeśli wydaje się, że może nie być potrzebny, prawdopodobnie nie jest. Jest to szczególnie przydatne w porównaniach.
Przykład:
vs.
Jeśli potrzebujesz rozgałęzić skrypt w oparciu o wynik pojedynczego testu, który może mieć wiele wyników,
switch
może czasami pasować lub pobić instrukcję if.Przykład (zamiana vs. if / else - remis):
vs.
Lub (zmień vs. if / elseif / else - przełącznik wygrywa o 15):
vs.
Jeśli przełącznik faktycznie opiera się na pewnych wynikach matematycznych, takich jak powyższa operacja modulo, możesz całkowicie zastąpić przełącznik tablicą. Tutaj zapisuje kolejne 13 znaków i jest nawet krótszy niż oryginalna dwustopniowa instrukcja if / else. (Podziękowania dla Danko Durbic za ten kawałek.)
Jeśli będziesz często używał określonego polecenia, zwłaszcza bez wcześniejszego aliasu krótkiej ręki, wcześnie skonfiguruj alias jednoznakowy.
Przykład:
vs.
źródło
('even','odd')[$x%2]
FYI.Hermetyzacja polecenia definiującego zmienną w nawiasach umożliwia przekazanie definicji zmiennej bezpośrednio do innych poleceń.
Na przykład możesz ustawić $ x, a następnie ustawić $ y na podstawie wartości $ x w jednym ujęciu za pomocą tego:
Zamiast tego:
Możesz ustawić $ h i wyprowadzić go za pomocą:
Zamiast tego:
źródło
($x=New-Object Windows.Forms.Form).Controls.Add($t)
Przełącznik może działać jak pętla, gdy otrzyma tablicę. Na przykład:
Wyjdzie:
Nie jestem do końca pewien, gdzie to będzie przydatne, ale spodziewam się, że przyda się komuś przez jakiś czas.
źródło
ForEach-Object
, aswitch
wewnątrz tego. Jest to na przykład (w prawdziwym świecie) kod bardzo fajny do pisania szybkich parserów plików tekstowych, w których musisz robić różne rzeczy w zależności od tego, które wyrażenie regularne pasuje do linii.switch -File $path
jestZamień na
[math]::pow
mnożenie. ZamiastMożesz pisać
Działa to dla wykładników liczb całkowitych> = 0.
źródło
iex
... Alias dlaInvoke-Expression
Operatory porównania działają na kolekcjach wartości, zwracając pasujące wartości:
przyniesie
3
,4
i5
. W niektórych przypadkach może to pomóc zaoszczędzić w inny sposób dłużej|?{$_...}
.-match
jest również operatorem porównania.źródło
1..5-gt2
W miarę możliwości używaj aliasów. Istnieje kilka przydatnych:
źródło
Chcesz znaleźć maksimum lub minimum zbioru wartości? Wypróbowany
lub
już?
Po prostu posortuj i użyj ostatniego lub pierwszego elementu:
źródło
0
,1
,2
,3
,4
,5
,6
,7
,8
lub9
, byłoby zapisać bajt do napisania znanej długości zamiast-1
.Skracanie nazw nieruchomości
Niestety, w przeciwieństwie do parametrów, właściwości / metody (wszystko dostępne za pomocą kropki
.
) zwykle nie może być skrócone do jednoznacznej formy.Ale niektóre aplety poleceń może działać nazw właściwości i podjąć symbole wieloznaczne, a tam są mało znane zestawy parametrów z
%
i?
które mogą być użyteczne.Zwykle przekazujemy blok skryptu i odnosimy się do elementu za pomocą
$_
, ale istnieje inna forma, która przyjmuje nazwę właściwości i akceptuje symbol wieloznaczny.W przypadku takiej właściwości
.Length
nie możemy użyć magii v3, która normalnie działałaby na tablicy, ponieważLength
jest ona właściwością samej tablicy, więc powyższe dwie wartości można wykorzystać do uzyskania długości poszczególnych elementów. Jestselect
nieco krótszy.Ale
%
może wziąć nazwę właściwości bezpośrednio i zwrócić tę wartość:Które można skrócić za pomocą symboli wieloznacznych. Symbol wieloznaczny musi zostać rozpoznany jako pojedyncza właściwość (lub metoda, więcej na ten temat później), więc jeśli nie, wyśle pomocny błąd, wskazując dokładnie, do których elementów mógłby rozwiązać.
W przypadku
Length
,Le*
jest zwykle najkrótszy. Nawet w przypadku pojedynczego ciągu ta metoda jest o 1 bajt krótsza niż zwykłe użycie właściwości.Ale w zależności od tego, co z tym robisz, może być gorzej. Możesz
$a.Length*5
zrobić to tylko za pomocą wyrażenia potoku, które musiałbyś zawinąć($a|% Le*)*5
; może nadal warto, jeśli jest przeciwko tablicy, ale chodzi o to, że nie zawsze jest odpowiednia jako prosta zamiana.Działa również z metodami i możesz pominąć tę,
()
która sprawia, że pełna nazwa ma taką samą długość, ale takie samo ograniczenie, jak powyżej, dotyczące czasami konieczności jej zawijania.Metoda musi mieć przeciążenie, które nie przyjmuje parametrów(możesz przekazać argumenty, umieszczając je po nazwie metody, co jest naprawdę fajne):Z argumentami:
Nie są one dokładnie takie same, ponieważ
-replace
operator zastępuje wyrażenia regularne, ale jeśli po prostu zastępujesz ciąg znaków, użycie metody może być (teraz) krótsze; pomaga to, że ciągi są argumentami cmdlet zamiast argumentów metod, więc nie trzeba ich cytować.Właściwości Where-Object
?
może również przyjmować (częściowe) nazwy właściwości i stosować do niej „operator” (w postaci parametrów przełącznika). Ponownie może to być krótsze niż użycie standardowegoWhere-Object
podejścia do blokowania skryptów, jeśli nazwa właściwości jest wystarczająco długa i unikalna.źródło
.ToString()
!Znajdowanie sumy na dłuższą metę:
Krótsza droga:
A nawet krócej:
źródło
Średniki i łamanie linii są wymienne. Kod w golfa jest często bardziej czytelny, jeśli nie jest zablokowany w jednej linii. A długość jest wciąż taka sama (pod warunkiem, że użyjesz U + 000A jako podziału linii, który PowerShell obsługuje bez problemów).
źródło
Get
Czasownik jest dorozumiany. Może to skrócić dowolnyGet-Frob
do sprawiedliwegoFrob
. Częstymi uczestnikami sądate
lubrandom
.Zauważ, że w niektórych przypadkach nie zadziała to poprawnie, ponieważ na swojej ścieżce mogą znajdować się narzędzia GNU (lub inne programy natywne, które się zderzają). Kolejność wyszukiwania poleceń w tym przypadku wydaje się preferować program macierzysty przed rozważeniem polecenia cmdlet z
Get-
usuniętym:źródło
nal g Get-Random
aby później zapisać znaki. Zmiana go nanal g Random
powoduje zawieszenie się skryptu w nieskończoność (lub przynajmniej zajmuje nadmierną ilość czasu na przetworzenie - nie miałem cierpliwości, aby czekać, aż się skończy, ale zajmuje kilka rzędów wielkości dłużej niż pierwotna forma przed aborcją).Measure-Command
inwokacje (100 razyGet-Random
vs.random
) mówią mi, że jest to około 500 razy wolniej. Szczerze mówiąc, nie wiedziałem o tym wcześniej. Ale warto o tym pamiętać, zwłaszcza w pętlach z wieloma iteracjami. Mając na uwadze powyższe, kod golfed powinien być krótki, nie szybko ( który mówi, że jest do bani musiał czekać dwa dni na odpowiedź na problem Projekt Euler).Get-Variable
Vs.gv
i dostał podobną porównanie.Get-
. To dość paskudny wzdęcie w czasie wykonywania dla oszczędności zaledwie 4 znaków.for
Pętle mogą mieć w nagłówku wszystko od 0 do trzech instrukcji:Nieskończona pętla:
Pętla z inicjalizacją:
Pętla z warunkami inicjalizacji i zakończenia:
W takich przypadkach dodatkowe średniki na końcu można pominąć (jest to wyraźnie określone w specyfikacji języka , więc nie jest to szczegół implementacji) w przeciwieństwie do języków podobnych do C, które zawsze wymagają dokładnie trzech instrukcji.
To również sprawia, że
while
jest nieco krótszy. Porównaći
Dzięki dodatkowej premii, którą możesz trzymać w poprzedniej linii (jeśli taka istnieje) również w tej linii
for
bez dodatkowych kosztów (a nawet uratowania postaci).źródło
Jeśli przypisujesz tablicę, o której wiesz, że będzie miała tylko dwie wartości, nie używaj indeksowania.
Coś takiego:
Można to łatwo zmienić w:
Może to być również przydatne, jeśli potrzebujesz tylko pierwszego elementu tablicy:
źródło
$a="apple";$o="orange"
ma identyczną długość. Są to dłuższe tablice, które czasami można dość ładnie zoptymalizować, np. Umieszczając wszystkie elementy w łańcuchu z separatorem, a następnie używając-split
(najlepiej użyć białych znaków jako separatora, ponieważ wtedy-split
wystarczy jednoargument ).Przesyłanie do łańcucha:
vs.
Rzutowanie na ciąg znaków w ten sposób może być również użyte do spłaszczenia tablicy ciągów zamiast łączenia:
vs.
Rzutowanie ciągu na typ numeryczny:
vs.
Również bardzo przydatne, aby wiedzieć, że PowerShell zawsze przyjmuje typ lewego operandu, aby określić końcowy typ wyrażenia i konwersje do zastosowania:
co może pomóc określić, gdzie są niepotrzebne rzuty.
źródło
Nie zapominaj, że nie zawsze musisz podać pełną nazwę parametru, a niektóre parametry są pozycyjne.
... można przyciąć do ...
... ponieważ „I” w tym przypadku wystarczy, aby jednoznacznie zidentyfikować
InputObject
na podstawie innych prawidłowych parametrów tego polecenia.Możesz przyciąć go dalej do ...
... ponieważ
InputObject
jest parametrem pozycyjnym.Rurociągi są zwykle krótsze niż podawanie obiektów jako parametru, szczególnie gdy może to wyeliminować potrzebę nawiasów. Przytnijmy nasz generator liczb losowych dalej ...
Szukaj też innych sposobów osiągnięcia tego samego, nawet jeśli nie możesz zmienić polecenia. W powyższym przypadku możesz to zrobić:
Lub dołączając inną sugestię *:
** Uwaga: Pominięcie
Get-
nazwy polecenia może zwiększyć czas działania o około 50 000%. Nieźle, jeśli potrzebujesz polecenia tylko raz, ale ostrożnie używaj go w długich pętlach. *I w ten sposób można powalić proste polecenie do jednej trzeciej jego wielkości.
źródło
Fałszywy operator trójskładnikowy. Możesz przypisać bezpośrednio z
if
wyciągu:Ale możesz użyć 2-elementowej tablicy i użyć testu, aby się do niej zindeksować. Wyniki $ falsey otrzymują element 0, $ wyniki prawdziwe zawierają element 1:
NB. że naprawdę robi to indeksowanie tablic, a jeśli test da wartość, która może być wyrzucona na liczbę całkowitą, poprosisz o element poza granicami tablicy i otrzymasz $ null z powrotem, i będziesz musiał zrobić to,
!(test)
aby wymusić rzuć wynik na bool, z odwróconymi opcjami.źródło
$()
. Zasadniczo istniało rozróżnienie między wykorzystaniem potoków wykonanych z poleceń i instrukcji jako wyrażeń. Wygląda na to, że już go nie ma, przynajmniej w PowerShell 5.Gdy używasz liczby jako argumentu dla operatora, który w innym przypadku wymagałby łańcucha, możesz użyć liczby bezpośrednio. Porównać
vs.
Działa
-split
również z. Argument jest zawsze najpierw konwertowany na ciąg znaków.źródło
-replace
również.-replace
działa również bez drugiego argumentu, jeśli chcesz usunąć dopasowania,Całkowita wartość
Z
Zamiast
posługiwać się
Oczywiście oszczędności są anulowane, jeśli potrzebne są nawiasy.
źródło
Jeśli musisz wyciszyć błędy, oczywistym wariantem byłoby
To jednak zdecydowanie za długo. Krótszym wariantem jest uruchomienie
try
bloku jako bloku skryptu i po prostu przekierowanie błędów do nieuzbrojonej zmiennej ($null
byłby zwykły, ale to wciąż za długo):Oszczędza to pięć cennych bajtów (jeśli nie świat).
źródło
Za pomocą
$ofs
zmiennej szczególną zmianę O utput F ield S eparator używane podczas stringifying tablicę. Przydatne, jeśli trzeba wielokrotnie przekształcać tablice w ciągi.Na przykład:
Zapisuje 2+ n znaków na 2
-join
, gdzie n jest długością separatora, i zapisuje dodatkowe 5+ n dla 3-join
i każdego później.źródło
Automatyczne zmienne mają wartości logicznych dla prawdziwych i fałszywych jak
$true
i$false
ale można uzyskać podobne rezultaty stosując nie logicznego operatora!
i liczby całkowite 0 i 1 (lub dowolną niezerową liczbę całkowitą).Niemal wszystkie wyrażenia programu PowerShell można oceniać jako wartości logiczne. Tak długo, jak masz świadomość, jak niektóre dane są oceniane, możesz otrzymać boolean i nigdy nie musisz ich jawnie przesyłać. Wykonując te czynności, należy pamiętać o wartości LHS.
Istnieją inne przykłady, ale możesz łatwo przetestować, wykonując obsadę
źródło
$null
to falsey. Pusty ciąg (i zmienne ustawione na pusty ciąg) są falsey. Itd. Można to następnie wykorzystać do skrócenia indeksowania do tablicy (np. Podczas wykonywaniaif
/else
), jak to było używane w FizzBuzz .int
s jest tylko krótszebool
. Możesz użyć0
i1
równie dobrze. Niejawne konwersje bardzo w tym pomagają (które często można wymusić u niektórych operatorów).Invoke-Expression
iGet-Random
może również pobierać dane wejściowe potoku zamiast argumentów.W
iex
tym celu można zapisać nawiasy na niektóre wyrażenia:W takim przypadku
random
pozwala to na pewną optymalizację zwykłego przypadku:Drugi sposób korzystania z niego polega po prostu na wybraniu elementu z listy.
-c
Argumentem może być udzielona w celu umożliwienia więcej niż jednego wyboru.źródło
Rozważ przechowywanie powtarzających się bloków skryptów w zmiennych zamiast używania funkcji.
Zamierzałem użyć tego, aby zapisać niektóre znaki w mojej implementacji Rock, Paper, Scissors, zanim zdałem sobie sprawę, że ponowne zapisanie funkcji jako zmiennej sprawiło, że nawet zmienna stała się niepotrzebna. Może to być jednak przydatne w przypadku innych skryptów, w których ten sam kod jest uruchamiany wiele razy.
vs.
źródło
params(...)
zajęłoby więcej miejsca niż oszczędza definicja funkcji. Powiązane: Zastosowaniefilter
nafunction
kiedy można to zrobić.$args
aby uniknąć potrzebyparams
; tj.$x={$args[0]+2}
(lub nawet$x={2+"$args"}
); może uratować postać lub 2 w niektórych okolicznościach. Możesz także połączyć to z inną sztuczką dla wielu parametrów:$x={$a,$b=$args;$a+$b+3}
Można użyć
$s|% t*y
zamiast[char[]]$s
podzielić ciąg do tablicy char. Na podstawie odpowiedzi TessellatingHeckler :% t*y
rozwija się do| ForEach-Object -Method ToCharArray
ekwiwalentu. z"$args".ToCharArray()
Na przykład porównaj
i
i
Przydaje się
$args
zwłaszcza:$args|% t*y
źródło
%
Kilka razy korzystałem z tej sztuczki również dla członków, ale większość mojego golfa poprzedza tę funkcję ;-). Jest to również dość ogólna technika: spróbuj znaleźć kombinację liter / symboli wieloznacznych, która pasuje do właściwości / metody, której potrzebujesz (i jest krótsza niż rzeczywista).$s|% *per
za$s.toUpper()
i$s|% *wer
za$s.toLower()
. Zgadzam się, że to całkiem miłe.|% t* "ddd\:hh\:mm\:ss"
for[TimeSpan].toString("ddd\:hh\:mm\:ss")
Użyj logiki boolowskiej zamiast liczników if w pętli
Załóżmy, że dodajesz wszystkie liczby parzyste od 1 do 10 ...
2+4+6+8+10=30
Możesz użyć logicznej negacji, aby ją skrócić
aby zaoszczędzić bajt, ale co powiesz na zamiast tego użyj niejawnego rzutowania booleanów na ints i wrzuć warunek do akumulatora
Zapisuje 6 bajtów w tym przykładzie.
źródło
Konwersja liczb zmiennoprzecinkowych na liczby całkowite w programie PowerShell to trochę pole minowe. Domyślnie konwersja wykonuje zaokrąglanie za pomocą Bankers Rounding, które nie zawsze przycina przecinek dziesiętny i pozostawia mniejszą liczbę całkowitą, lub zawsze zaokrągla 0,5 do następnej liczby, jak ludzie robią przypadkowo, zaokrągla wyrównanie w jedną stronę i szanse w drugą stronę - może to być zaskakującym, np
i przerwać obliczenia kodegolfa. Wiele innych popularnych języków używa skrótu, dlatego pytania w golfa często wymagają obcięcia. Możesz sięgnąć
[Math]::Floor()
po następną najlepszą rzecz, ale uważaj, to zachowuje się tak samo jak obcięcie dla liczb dodatnich, ale zmniejsza liczby ujemne - dalej od zera.[Math]::Truncate()
jest to, czego potrzebujesz, aby dostosować zachowanie PS do domyślnego zaokrąglenia w innym języku, ale jest to wiele znaków.Regex zastępując cyfry po przecinku, może pomóc zapisać kilka znaków:
źródło
Odwracanie tablicy
Przydaje się w wielu ascii-artystycznych wyzwaniach, w których produkcja jest odzwierciedlona w pewien sposób.
Załóżmy, że masz
Tradycyjna metoda odwracania jest długa, nudna i nie pozostawia tablicy w potoku do natychmiastowego użycia.
Indeksowanie bezpośrednio do tablicy w odwrotnej kolejności pozwala zaoszczędzić kilka bajtów, ponieważ pozostawia wyniki w potoku, ale wciąż jest dość długi:
Zamiast tego spróbuj użyć pętli
źródło
Począwszy od PowerShell Core 6, możesz także używać zakresów dla znaków:
co może zastąpić znacznie bardziej kłopotliwe
źródło
[char[]](65..90)
to także przydatny sposób na wygenerowanie alfabetu