Wskazówki dotyczące gry w golfa w programie PowerShell

45

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 .

Joey
źródło
3
Kiedy przejrzałem „PowerShell golf”, był to pierwszy hit!
Matt

Odpowiedzi:

24

Potęgi 10 literałów z notacją naukową:

4e6 = 4000000

Potęgi 2 literałów:

4KB = 4096
4MB = 4194304
4GB = 4294967296

# TB and PB suffixes also exist, but less useful for golf.

Może się przydać.

Joey
źródło
19

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-Objectza pośrednictwem %aliasu zamiast używania for.

for($x=1;$x-le10;$x++){...}

vs

1..10|%{...}

Iszi
źródło
18

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:

$x-eq$i-and$x-ne9

vs.

$x -eq $i -and $x -ne 9

Jeśli potrzebujesz rozgałęzić skrypt w oparciu o wynik pojedynczego testu, który może mieć wiele wyników, switchmoże czasami pasować lub pobić instrukcję if.

Przykład (zamiana vs. if / else - remis):

if($x%2-eq0){'even'}else{'odd'}

vs.

switch($x%2){0{'even'}1{'odd'}}

Lub (zmień vs. if / elseif / else - przełącznik wygrywa o 15):

if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}

vs.

switch($x%2){0{'even'}1{'odd'}2{'error'}}

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.)

('even','odd','error')[$x%2]

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:

nal g Get-Random;g 10;g 10;g 10

vs.

Get-Random 10;Get-Random 10;Get-Random 10
Iszi
źródło
('even','odd')[$x%2]FYI.
Nieprawidłowy 1
15

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:

$y=($x=1)+1

Zamiast tego:

$x=1;$y=$x+1

Możesz ustawić $ h i wyprowadzić go za pomocą:

($h='Hello World!')

Zamiast tego:

$h='Hello World!';$h
Iszi
źródło
1
Jest to szczególnie przydatne do wywoływania metod na obiektach. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD
14

Przełącznik może działać jak pętla, gdy otrzyma tablicę. Na przykład:

$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
    'a'{'FOO'}
    'b'{'BAR'}
    default{'MEH'}
}

Wyjdzie:

FOO
BAR
MEH

Nie jestem do końca pewien, gdzie to będzie przydatne, ale spodziewam się, że przyda się komuś przez jakiś czas.

Iszi
źródło
2
Jest poręczny każdym razem trzeba ForEach-Object, a switchwewną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.
Joey
To jest ... cholernie dziwne. Tablica nie powinna pasować do znaku, ale tak jest.
kot
@Joey To właśnie switch -File $pathjest
TheIncorriable1
Nie wszystko, co zostało przeanalizowane, zdarza się, że jest plikiem.
Joey,
12

Zamień na [math]::powmnożenie. Zamiast

[math]::pow($a,$b)

Możesz pisać

"$a*"*$b+1|iex

Działa to dla wykładników liczb całkowitych> = 0.

Danko Durbić
źródło
Musiałem zobaczyć tę odpowiedź, aby zrozumieć iex... Alias ​​dlaInvoke-Expression
HeatfanJohn
11

Operatory porównania działają na kolekcjach wartości, zwracając pasujące wartości:

1..5 -gt 2

przyniesie 3, 4i 5. 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.

Joey
źródło
1
Zwróć uwagę, że w tym przykładzie nie potrzebujesz spacji1..5-gt2
Matt
1
Wiem; chodziło raczej o pokazanie techniki. Spacje są w osobnej odpowiedzi .
Joey,
11

W miarę możliwości używaj aliasów. Istnieje kilka przydatnych:

?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression
Joey
źródło
11

Chcesz znaleźć maksimum lub minimum zbioru wartości? Wypróbowany

(...|measure -ma).Maximum

lub

(...|measure -mi).Minimum

już?

Po prostu posortuj i użyj ostatniego lub pierwszego elementu:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
Joey
źródło
1
A jeśli znasz długość zbioru wartości, a jest on mniejszy niż 10 ...
wizzwizz4 10.01.2016
@ wizzwizz4: Och, maksymalne długości często można zastosować w sposób kreatywny, niekoniecznie wynoszący 10. Chociaż w tym konkretnym przypadku nie pamiętam wystąpienia, w którym kiedykolwiek pomogło.
Joey,
1
To znaczy, jeśli ostateczna pozycja jest znana 0, 1, 2, 3, 4, 5, 6, 7, 8lub 9, byłoby zapisać bajt do napisania znanej długości zamiast -1.
wizzwizz4,
10

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.

$o|select Le*  
$o|%{$_.Length}

W przypadku takiej właściwości .Lengthnie możemy użyć magii v3, która normalnie działałaby na tablicy, ponieważ Lengthjest 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. Jest selectnieco krótszy.

Ale %może wziąć nazwę właściwości bezpośrednio i zwrócić tę wartość:

$a|% Length

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.

$a.Length                # 9   #(doesn't work on array)
$a|%{$_.Length}          # 15
$a|% Le*                 # 8

Ale w zależności od tego, co z tym robisz, może być gorzej. Możesz $a.Length*5zrobić 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):

$a.ToUpper()             # 12
$a|% *per                #  9

Z argumentami:

'gaga'-replace'g','r'    # 21
'gaga'|% *ce g r         # 16

Nie są one dokładnie takie same, ponieważ -replaceoperator 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 standardowego Where-Objectpodejścia do blokowania skryptów, jeśli nazwa właściwości jest wystarczająco długa i unikalna.

$a|?{$_.Length-gt5}      # 19
$a|? Le* -GT 5           # 14

($a|% Le*)-gt5           # 14 - Lengths, not objs
briantist
źródło
1
Jedno z niewielu miejsc, w których wymagane są białe znaki. Niezłe znalezisko. Mogę wymyślić kilka obszarów, w których to skróci rzeczy.
AdmBorkBork
Niezła edycja Joey! Dzięki.
briantist
Znalazłem sposób, aby go skrócić ;-) ... smutną rzeczą jest to, że jako całość jest to znowu rurociąg, co nieco ogranicza jego użyteczność. A raczej istnieje wiele miejsc, w których trzeba by ponownie zawinąć go w nawiasy, aby uzyskać wyrażenie. Ale niewiele technik golfa jest bez kompromisów ...
Joey
1
@ConnorLSW ah tak Chciałem to zaktualizować, ponieważ zdałem sobie sprawę, że możesz przekazywać argumenty w ten sposób, co znacznie zwiększa jego użyteczność. Świetne wykorzystanie .ToString()!
briantist
2
@ briantist zamieniło to PowerShell w język bardziej konkurencyjny, naprawdę odcina niektóre irytujące pełne rozmowy .Net.
colsw
9

Znajdowanie sumy na dłuższą metę:

(...|measure -s).Sum

Krótsza droga:

...|%{$s+=$_};$s

A nawet krócej:

...-join'+'|iex
Joey
źródło
9

Ś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).

Joey
źródło
2
Chwila, martwimy się o czytelność ?!
Kevin Cox
4
Jeśli nie ma to wpływu na długość ... dlaczego nie?
Joey,
Czy to technicznie nie robi różnicy, ponieważ średnik jest o jeden mniej znaków niż \ r \ n? Tylko w Uniksie jest to liczba pojedyncza \ n.
Vasili Syrakis
2
@Vasili: Możesz zapisać pliki w porządku tylko z U + 000A między wierszami. PowerShell nie narzeka. Przy okazji, co już napisałem w odpowiedzi. Podziały wierszy są właściwością pliku , a nie systemu operacyjnego, w którym są używane. Nikt nie mówi, że nie można używać zakończeń linii uniksowych w systemie Windows.
Joey,
@Joey Jeśli użyłeś świeżej instalacji systemu Windows do szybkiego programowania, zauważysz, że Notatnik nie działa dobrze z \ x0a
Stan Strum
9

GetCzasownik jest dorozumiany. Może to skrócić dowolny Get-Frobdo sprawiedliwego Frob. Częstymi uczestnikami są datelub random.

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:

PS Home:\> date

Freitag, 15. November 2013 07:13:45


PS Home:\> $Env:Path += ';D:\Users\Joey\Apps\GnuWin32\bin'
PS Home:\> date
Fr Nov 15 07:14:13 W. Europe Standard Time 2013
Joey
źródło
To nie całkiem zawsze układa się zgodnie z oczekiwaniami. Mam skrypt, który zaczyna się od, nal g Get-Randomaby później zapisać znaki. Zmiana go na nal g Randompowoduje 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ą).
Iszi
2
Dwie krótkie Measure-Commandinwokacje (100 razy Get-Randomvs. 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).
Joey,
1
Moim problemem było uruchomienie 10 000 powtórzeń scenariusza Monty Hall, z których każdy wymagał trzech powtórzeń Get-Random. Wzrost czasu przetwarzania o 50 000%, pomnożony przez 30 000 przebiegów, jest dość nieprzyjemny.
Iszi
Łał. Wygląda na to, że to samo prawdopodobnie odnosi się do dowolnego aliasu. Przetestowane Get-VariableVs. gvi dostał podobną porównanie.
Iszi
1
To może być to. Zrobiłem trochę matematyki i doszedłem do wniosku, że mój skrypt Monty Hall powinien zająć około 1,5 godziny (zwykle 10-11 sekund), aby uruchomić bez niego Get-. To dość paskudny wzdęcie w czasie wykonywania dla oszczędności zaledwie 4 znaków.
Iszi
8

for Pętle mogą mieć w nagłówku wszystko od 0 do trzech instrukcji:

Nieskończona pętla:

for(){}

Pętla z inicjalizacją:

for($n=0){}

Pętla z warunkami inicjalizacji i zakończenia:

for($n=0;$n-lt7){}

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 whilejest nieco krótszy. Porównać

while(...){}

i

for(;...){}

Dzięki dodatkowej premii, którą możesz trzymać w poprzedniej linii (jeśli taka istnieje) również w tej linii forbez dodatkowych kosztów (a nawet uratowania postaci).

Joey
źródło
8

Jeśli przypisujesz tablicę, o której wiesz, że będzie miała tylko dwie wartości, nie używaj indeksowania.

Coś takiego:

$a="apple","orange"
$a[0] # apple
$a[1] # orange

Można to łatwo zmienić w:

$a,$o="apple","orange"
$a # apple
$o # orange

Może to być również przydatne, jeśli potrzebujesz tylko pierwszego elementu tablicy:

$a,$b=1..10
$a # 1
$b # 2..10
SomeShinyObject
źródło
W tym przypadku (ze sznurkami) $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 -splitwystarczy jednoargument ).
Joey
8

Przesyłanie do łańcucha:

[string]$x

vs.

"$x"

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:

$a = @('a','b','c')
$a -join ' '

vs.

$a = @('a','b','c')
"$a"

Rzutowanie ciągu na typ numeryczny:

[int]$x     [float]$x

vs.

+$x

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:

'1'+2    -> '12'
1+'2'    -> 3

co może pomóc określić, gdzie są niepotrzebne rzuty.

Joey
źródło
6

Nie zapominaj, że nie zawsze musisz podać pełną nazwę parametru, a niektóre parametry są pozycyjne.

Get-Random -InputObject (0..10)

... można przyciąć do ...

Get-Random -I (0..10)

... ponieważ „I” w tym przypadku wystarczy, aby jednoznacznie zidentyfikować InputObjectna podstawie innych prawidłowych parametrów tego polecenia.

Możesz przyciąć go dalej do ...

Get-Random (0..10)

... ponieważ InputObjectjest 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 ...

0..10|Get-Random

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ć:

Get-Random 11

Lub dołączając inną sugestię *:

Random 11

** 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.

Iszi
źródło
6

Fałszywy operator trójskładnikowy. Możesz przypisać bezpośrednio z ifwyciągu:

$z=if($x-eq$y){"truth"}else{"false"}

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:

$z=("false","true")[$x-eq$y]

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.

TessellatingHeckler
źródło
Pierwszy fragment kodu nie działał w pewnym momencie (starsze wersje programu PowerShell), o ile dobrze pamiętam, co spowodowało konieczność jego owinięcia $(). 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.
Joey
Ponadto, jeśli elementy tablicy są niestatyczne, oba są analizowane i przetwarzane w ramach tworzenia tablicy, zanim nastąpi indeksowanie i wynik zostanie przypisany. Na przykład .
AdmBorkBork
6

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ć

...-join'0'

vs.

...-join0

Działa -splitrównież z. Argument jest zawsze najpierw konwertowany na ciąg znaków.

Joey
źródło
Dla porównania działa to -replacerównież.
AdmBorkBork
-replacedziała również bez drugiego argumentu, jeśli chcesz usunąć dopasowania,
Joey,
5

Całkowita wartość

Z

$n=-123

Zamiast

[math]::abs($n)

posługiwać się

$n-replace'-'

Oczywiście oszczędności są anulowane, jeśli potrzebne są nawiasy.

Rynant
źródło
Lub jeśli potrzebujesz wyniku po lewej stronie operatora ;-)
Joey
5

Jeśli musisz wyciszyć błędy, oczywistym wariantem byłoby

try{ <# something that throws errors #> }catch{}

To jednak zdecydowanie za długo. Krótszym wariantem jest uruchomienie trybloku jako bloku skryptu i po prostu przekierowanie błędów do nieuzbrojonej zmiennej ( $nullbyłby zwykły, ale to wciąż za długo):

.{ <# something that throws errors #> }2>$x

Oszczędza to pięć cennych bajtów (jeśli nie świat).

Joey
źródło
5

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:

$a=1,2,3,4
$a-join',';$a-join','
$ofs=',';"$a";"$a"

Zapisuje 2+ n znaków na 2 -join, gdzie n jest długością separatora, i zapisuje dodatkowe 5+ n dla 3 -joini każdego później.

AdmBorkBork
źródło
1
Niestety bardzo rzadko przydatna (przynajmniej do tej pory podczas gry w golfa - staram się rozebrać ją do jednego połączenia na końcu).
Joey,
5

Automatyczne zmienne mają wartości logicznych dla prawdziwych i fałszywych jak $truei $falseale można uzyskać podobne rezultaty stosując nie logicznego operatora !i liczby całkowite 0 i 1 (lub dowolną niezerową liczbę całkowitą).

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

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.

  • Liczba całkowita 0 jest fałszem, a niezerowe liczby całkowite są oceniane jako prawda.
  • łańcuchy o niezerowej długości są prawdziwe, a łańcuchy puste lub puste (i same null) są fałszywe.

Istnieją inne przykłady, ale możesz łatwo przetestować, wykonując obsadę

PS C:\Users\matt> [bool]@(0)
False
Matt
źródło
1
Wiele innych typów danych ma również podobny status. Domyślnie niezainicjowane zmienne $nullto 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 wykonywania if/ else), jak to było używane w FizzBuzz .
AdmBorkBork
@TimmyD Very true. Używanie ints jest tylko krótsze
Matt
@ TimmyD Chciałem odpowiedzieć na fizzbuzz, dopóki nie zobaczyłem twojego .... Nie mogę tego pobić .... przynajmniej jeszcze nie
Matt
Należy zauważyć, że w wielu przypadkach nie faktycznie trzebabool . Możesz użyć 0i 1równie dobrze. Niejawne konwersje bardzo w tym pomagają (które często można wymusić u niektórych operatorów).
Joey,
4

Invoke-Expressioni Get-Randommoże również pobierać dane wejściowe potoku zamiast argumentów.

W iextym celu można zapisać nawiasy na niektóre wyrażenia:

iex 1..5-join'+'   # won't work
iex(1..5-join'+')  # does work, but has extra parentheses
1..5-join'+'|iex   # doesn't need the parentheses

W takim przypadku randompozwala to na pewną optymalizację zwykłego przypadku:

random -mi 10 31   # gets a random integer between 10 and 30
10..30|random      # much better :-)
(random 21)+10     # if needed in another expression that doesn't require extra
                   # parentheses

Drugi sposób korzystania z niego polega po prostu na wybraniu elementu z listy. -cArgumentem może być udzielona w celu umożliwienia więcej niż jednego wyboru.

Joey
źródło
4

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.

function Hi{echo 'Hello, World!'};Hi

vs.

$Hi={echo 'Hello, World!'};&$Hi
Iszi
źródło
2
Przydatny w przypadku funkcji, które nie przyjmują argumentów. W przeciwnym razie params(...)zajęłoby więcej miejsca niż oszczędza definicja funkcji. Powiązane: Zastosowanie filterna functionkiedy można to zrobić.
Joey,
Możesz użyć, $argsaby uniknąć potrzeby params; 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}
JohnLBevan
4

Można użyć $s|% t*yzamiast [char[]]$spodzielić ciąg do tablicy char. Na podstawie odpowiedzi TessellatingHeckler : % t*yrozwija się do | ForEach-Object -Method ToCharArrayekwiwalentu. z"$args".ToCharArray()

Na przykład porównaj

$s|% t*y

i

[char[]]$s

i

$s.ToCharArray()

Przydaje się $argszwłaszcza:$args|% t*y

mazzy
źródło
1
To całkiem miłe. %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).
Joey,
Kolejne przydatne przykłady z odpowiedzi: $s|% *perza $s.toUpper()i $s|% *werza $s.toLower(). Zgadzam się, że to całkiem miłe.
mazzy
Jeszcze jeden przykład : |% t* "ddd\:hh\:mm\:ss"for[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy
Cóż, to tylko strata cytatów; nie potrzebujesz ich tutaj :-)
Joey
3

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

1..10|%{if($_%2-eq0){$o+=$_}};$o

Możesz użyć logicznej negacji, aby ją skrócić

1..10|%{if(!($_%2)){$o+=$_}};$o

aby zaoszczędzić bajt, ale co powiesz na zamiast tego użyj niejawnego rzutowania booleanów na ints i wrzuć warunek do akumulatora

1..10|%{$o+=$_*!($_%2)};$o

Zapisuje 6 bajtów w tym przykładzie.

AdmBorkBork
źródło
2
Jezus Chrystus. Planuję to zrobić w moim kodzie produkcyjnym w pracy, moi koledzy pokochają mnie za to.
Chavez
3

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

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

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:

[Math]::Truncate(1.5)
[Math]::Floor(1.5)
1.5-replace'\..*'

[Math]::Truncate($a)
[Math]::Floor($a)
$a-replace'\..*'
$a.split('.')[0]        # literal character split, not regex pattern split
TessellatingHeckler
źródło
3

Odwracanie tablicy

Przydaje się w wielu wyzwaniach, w których produkcja jest odzwierciedlona w pewien sposób.

Załóżmy, że masz

$a=1,2,3,4,5

Tradycyjna metoda odwracania jest długa, nudna i nie pozostawia tablicy w potoku do natychmiastowego użycia.

[array]::reverse($a)

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:

$a[($a.count-1)..0]

Zamiast tego spróbuj użyć pętli

$a|%{$a[-++$i]}
AdmBorkBork
źródło
indeksowanie wsteczne działa dobrze, gdy istnieje górna granica dla liczby
Joey
3

Począwszy od PowerShell Core 6, możesz także używać zakresów dla znaków:

'a'..'z'

co może zastąpić znacznie bardziej kłopotliwe

0..25|%{[char]($_+97)}
Joey
źródło
Och, to się przyda.
AdmBorkBork
1
[char[]](65..90)to także przydatny sposób na wygenerowanie alfabetu
Veska