PowerShell'de golf oynamak için ipuçları


45

Windows PowerShell'de golf oynamak için hangi genel ipuçlarınız var? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirleri arıyorum (en azından PowerShell'e özgüdür) (örneğin "yorumları kaldır" bir cevap değildir). Lütfen cevap başına bir ipucu gönderin.

- marcog'un sorusundan neredeyse birebir konuştu .


3
"PowerShell golf" googled zaman bu ilk hit oldu!
Matt

Yanıtlar:


24

Bilimsel gösterime sahip 10 değişmezin yetkileri:

4e6 = 4000000

2 değişmezin yetkileri:

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

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

İşe yarayabilirdi.


19

Eğer bir döngü çalıştırmak gerekiyor ve Biliyorsanız tam her zaman çalıştırmak için gereken kaç kez, içine bitişik Sayı dizisi boru düşünün ForEach-Objectyoluyla %takma kullanmak yerine for.

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

vs

1..10|%{...}


18

PowerShell'de çok fazla boşluk atlayabilirsiniz . İhtiyaç duymayacağına inanıyorsa, büyük olasılıkla değildir. Bu özellikle karşılaştırmalarda faydalıdır.

Örnek:

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

vs.

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

Komut dosyanızı birden fazla sonucu olabilecek tek bir testin sonucuna göre dallandırmanız switchgerekirse, bazen bir if ifadesiyle eşleşebilir veya yenilebilir.

Örnek (eğer / eğer başka bir yere bağlı - kravat):

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

vs.

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

Veya (eğer if / elseif / else - anahtar, kazancı 15 ile değiştirir):

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

vs.

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

Anahtar aslında bazı matematik sonuçlarına dayanıyorsa, yukarıdaki modulo işlemi gibi, anahtarı tamamen bir diziyle değiştirebilirsiniz. Burada, 13 karakter daha kaydeder ve orijinal iki-seçenek if / else ifadesinden bile kısadır. ( Bu bit için Danko Durbic'e teşekkürler .)

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

Belirli bir komutu çok fazla kullanacaksanız, özellikle önceden mevcut kısa el takma adı olmayanlardan birini kullanacaksanız, önceden tek bir karakter takma adı ayarlayın.

Örnek:

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

vs.

Get-Random 10;Get-Random 10;Get-Random 10

('even','odd')[$x%2]Bilginize.
TheIncorrigible1

15

Bir değişkeni parantez içinde tanımlayan komutu içine almak, değişkenin tanımını doğrudan diğer komutlara beslemenizi sağlar.

Örneğin, $ x ayarlayabilir ve ardından bir kerede $ x değerine göre $ y ayarını yapabilirsiniz:

$y=($x=1)+1

Bunun yerine:

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

$ H değerini ayarlayabilir ve bununla çıkış yapabilirsiniz:

($h='Hello World!')

Bunun yerine:

$h='Hello World!';$h

1
Bu özellikle nesnelerdeki yöntemleri çağırmak için kullanışlıdır. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD

14

Bir anahtar bir dizi verildiğinde, bir döngü gibi davranabilir. Örneğin:

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

Çıkacak:

FOO
BAR
MEH

Bunun nerede faydalı olacağından tam olarak emin değilim, ancak birileri için kullanışlı olacağını umuyorum.


2
İçinde her ForEach-Objectve her ihtiyacınız olduğunda kullanışlıdır switch. Örneğin, (gerçek dünyada) bir satırın hangi regex eşleşmesine bağlı olarak farklı şeyler yapmanız gereken metin dosyalarının hızlı çözümleyicileri yazmak için çok hoş bir koddur.
Joey

Bu ... çok garip. Bir dizinin bir karakterle eşleşmemesi gerekir, ancak olur.
kedi,

@Joey Bu ne switch -File $pathiçin
TheIncorrigible1 16:18

Ayrıştırılan her şey bir dosya gibi olmaz.
Joey,

12

[math]::powÇarpma ile değiştirin . Onun yerine

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

Yazabilirsin

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

Bu tamsayı üsleri için çalışır> = 0.


Anlamak için bu cevabı görmem gerekiyordu iex... Alias ​​forInvoke-Expression
HeatfanJohn

11

Karşılaştırma operatörleri, eşleşen değerleri döndürerek değer koleksiyonları üzerinde çalışır:

1..5 -gt 2

verecektir 3, 4ve 5. Bazı durumlarda bu, daha uzun süre tasarruf etmenize yardımcı olabilir |?{$_...}.

-match Bir karşılaştırma operatörü de.


1
Bu örnekte boşluklara ihtiyacınız olmadığını unutmayın1..5-gt2
Matt

1
Biliyorum; bu teknik gösterme hakkında daha fazla oldu. Boşluklar ayrı bir cevaptadır .
Joey

11

Mümkünse takma ad kullanın. Bir sürü faydalı var:

?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression

11

Bir değer koleksiyonunun maksimum veya minimumunu bulmak ister misiniz? Denenmiş

(...|measure -ma).Maximum

veya

(...|measure -mi).Minimum

zaten?

Sadece son veya ilk öğeyi sıralayın ve kullanın:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum

1
Ve, değerlerin koleksiyonunun uzunluğunu biliyorsanız ve 10'dan azsa ...
wizzwizz4

@ wizzwizz4: Oh, maksimum uzunluklar çoğu zaman yaratıcı bir şekilde kullanılabilir, zorunlu olarak 10 değildir. Her ne kadar bu özel durum için, hiç yardım ettiği bir örneği hatırlamıyorum.
Joey

1
Nihai madde olarak biliniyor Yani eğer 0, 1, 2, 3, 4, 5, 6, 7, 8veya 9, bunun yerine, bilinen uzunlukta yazmak için bayt tasarruf olur -1.
wizzwizz4

10

Emlak İsimlerinin Kısaltılması

Ne yazık ki, parametrelerden farklı olarak, özellikler / yöntemler (bir nokta ile erişilen herhangi bir şey .) genellikle belirsiz halleriyle kısaltılamaz.

Ancak bazı cmdlet'ler özellik adları üzerinde çalışabilir ve joker karakterler alabilir ve bunun için bilinen %ve ?yararlı olabilecek az sayıda parametre seti vardır .

Genellikle bir script bloğuna geçip öğeye atıfta bulunuruz $_, ancak özellik adını alan başka bir formu vardır ve bir joker karakteri kabul eder.

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

.LengthBizim gibi bir özellik ile normalde bir dizide çalışacak olan v3 sihirini kullanamayız, çünkü Lengthdizinin kendisinin bir özelliğidir, bu yüzden yukarıdaki iki bireysel üyelerin uzunluklarını almak için kullanılabilir. selectBiraz daha kısa bit geliyor.

Ancak %doğrudan bir mülk adını alabilir ve bu değeri döndürebilir:

$a|% Length

Bu joker karakterlerle kısaltılabilir. Joker karakter tek bir özelliğe çözümlenmelidir (veya daha sonra bununla ilgili bir yöntem), bu nedenle değilse, tam olarak hangi üyelere çözümlenebileceğini belirten yararlı bir hata verecektir.

Durumunda Length, Le*tipik olarak kısa süre. Tek bir dizgede bile, bu yöntem sadece özelliği kullanmaktan 1 bayt daha kısadır.

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

Ancak bununla ne yaptığınıza bağlı olarak, bu daha kötü olabilir. Yapabilirsiniz, $a.Length*5ancak onu ifade etmek için boru hattı ifadesiyle yapmak ($a|% Le*)*5; Bir diziye karşıysa yine de buna değer olabilir, ancak asıl nokta, her zaman düz bir ikame olarak uygun olmamasıdır.

Aynı zamanda yöntemlerle de çalışır ve hangisinin ()aynı uzunlukta bir tam isim yaptığını, ancak bazen onu sarmakla ilgili yukarıdakilerle aynı kısıtlamayı bırakabilirsiniz . Yöntemin parametresi olmayan bir aşırı yüklemesi olmalıdır (argümanları, yöntem adının arkasına yerleştirerek geçirebilirsiniz, bu gerçekten güzel):

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

Argümanlarla:

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

Bunlar, -replaceoperatörün bir regex yerine koymasıyla kesinlikle aynı değildir , ancak sadece bir dize yerine koyuyorsanız, (şimdi) yöntemi kullanmak daha kısa olabilir; Bu, dizgelerin metot argümanları yerine cmdlet argümanları olmalarına yardımcı olur, bu yüzden alıntılanmaları gerekmez.

Nesnenin Özellikleri

?(kısmi) özellik adlarını da alabilir ve buna bir "operatör" uygulayabilir (anahtar parametreleri şeklinde). Yine, bu Where-Objectözellik adı yeterince uzun ve benzersiz ise, standart scriptblock yaklaşımını kullanmaktan daha kısa olabilir .

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

($a|% Le*)-gt5           # 14 - Lengths, not objs

1
Boşluğun gerekli olduğu az sayıdaki yerden biri. Güzel bul olsa da. Bunun bazı şeyleri kısaltacağı birkaç alan düşünebilirim.
AdmBorkBork

Güzel düzenleme Joey! Teşekkürler.
briantist

Size kısaltmanın bir yolunu buldum ;-) ... bu konuda üzücü olan şey, bir bütün olarak tekrar bir boru hattı olması ve faydasını biraz sınırlandırması. Daha doğrusu, bir ifade almak için tekrar parantez içine sarmanız gereken birçok yer var. Ancak birkaç golf tekniği takas olmadan ...
Joey

1
@ConnorLSW ah evet Ben bu şekilde güncellemek istemiştim, o zamandan beri bu şekilde geçebileceğini fark ettim, ki faydası büyük ölçüde artıyor. Harika kullanımı .ToString()!
briantist

2
@briantist, bu PowerShell'i çok daha rekabetçi bir dile dönüştürdü, can sıkıcı ayrıntılı .NET ağ aramalarını gerçekten kesti.
colsw

9

Uzun yoldan bir miktar bulmak:

(...|measure -s).Sum

Daha kısa bir yol:

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

Ve daha da kısa:

...-join'+'|iex

9

Noktalı virgül ve satır kesmeleri değiştirilebilir. Tek satırda sıkışmazsa, golf kodu genellikle daha okunaklıdır. Ve uzunluk hala aynıdır (PowerShell'in sorunsuzca kullandığı satır sonu olarak U + 000A kullanmanız şartıyla).


2
Bekle, okunabilirlik konusunda endişeliyiz ?!
Kevin Cox

4
Eğer uzunluğu etkilemezse ... neden olmasın?
Joey

Noktalı virgül \ r \ n karakterinden daha küçük bir karakter olduğundan teknik olarak bir fark yaratmaz mı? Sadece Unix'te tekil bir \ n.
Vasili Syrakis

2
@Vasili: Dosyaları satırlar arasında yalnızca U + 000A ile gayet iyi kaydedebilirsiniz. PowerShell şikayet etmeyecek. Bu arada cevabını zaten yazdım. Satır sonları , kullanıldığı işletim sisteminin değil , dosyanın bir özelliğidir . Hiç kimse Windows'ta Unix satır sonlarını kullanamayacağınızı söylemez.
Joey

@Joey Bazı hızlı programlama yapmak için yeni bir pencere yüklemesi kullandıysanız, Not Defteri'nin \ x0a
Stan Strum ile

9

GetFiil ima edilir. Bu, herhangi bir kısaltabilir Get-Froblazım Frob. Sık yarışmacılar dateya da random.

Bunun bazı durumlarda düzgün çalışmayacağını unutmayın, çünkü yolunuzda GNU yardımcı programları (veya çakışan diğer yerel programlar) olabilir. Bu durumda komut arama sırası, Get-kaldırılan cmdlet'leri dikkate almadan önce yerel programı tercih ediyor gibi görünmektedir :

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

Bu vermez oldukça beklendiği gibi hep çalışmak. Daha nal g Get-Randomsonra karakterleri kaydetmek için başlayan bir betiğim var . Bunu değiştirmek nal g Random, betiğin süresiz olarak askıda kalmasına neden olacak (veya, en azından, işlemin yanlış bir süre alacağı - bitmesini beklemek için sabrım olmadı, ancak orijinal formdan daha uzun süren birkaç büyüklük siparişi alıyor) iptal etmeden önce).
Iszi,

2
İki kısa Measure-Commandçağrı (100 kere Get-Randomvs. random) bana bunun 500 kat daha yavaş olduğunu söylüyor. Bunu daha önce bilmiyordum, dürüst olmak gerekirse. Ancak, özellikle de birçok yinelemeli döngülerde akılda tutulması iyidir. Bu varlık (golfed kod hızlı değil, kısa olmalıdır, dedi o varlık bir proje Euler sorununa bir cevap iki gün beklemek zorunda berbat dedi).
Joey,

1
Benim sorunum, her biri üç Get-Random yineleme gerektiren 10,000 yineleme Monty Hall senaryosunu yürütmekti. İşlem süresinde% 50.000 artış, 30.000 çalıştırma ile çarpıldığında oldukça kötüdür.
Iszi

Vay. Aynı görünüyor muhtemelen herhangi bir takma ad için de geçerlidir. Test Get-VariableVS. gvve benzer bir karşılaştırma var.
Iszi

1
Bu olabilir. Biraz matematik yaptım ve Monty Hall senaryomun olmadan koşmak için yaklaşık 1,5 saat (normalde 10-11 saniye) alması gerektiğini düşündüm Get-. Bu sadece 4 karakter uzunluğunda bir tasarruf için çalışma zamanında oldukça sersemletici bir şişkinlik.
Iszi

8

for döngüler başlıklarında 0 ile üç ifade arasında herhangi bir şeye sahip olabilir:

Sonsuz döngü:

for(){}

Başlatma ile döngü:

for($n=0){}

İlklendirme ve son koşulu olan döngü:

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

Sonunda ek noktalı virgül ihmal edilebilir gibi durumlarda (açıkça belirtildiği oluyor dil şartnamede aksine bir uygulama ayrıntı değil bu yüzden,) C benzeri daima tam üç ifadeleri gerektiren dillerde.

Bu da whilebiraz daha kısa yapar . Karşılaştırmak

while(...){}

ve

for(;...){}

Bir önceki satıra ekleyebildiğiniz ilave bonus ile (varsa) forek ücret ödemeden de (hatta bir karakter tasarrufu bile).


8

Yalnızca iki değere sahip olacağını bildiğiniz bir dizi atadıysanız, dizin oluşturma kullanmayın.

Bunun gibi bir şey:

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

Kolayca şuna dönüştürülebilir:

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

Bu, aynı zamanda, bir dizinin ilk elemanına ihtiyaç duymanız durumunda faydalı olabilir:

$a,$b=1..10
$a # 1
$b # 2..10

Bu durumda (dizelerle) $a="apple";$o="orange"aynı uzunluktadır. Bazen oldukça iyi bir şekilde optimize edilebilecek uzun dizilerdir, örneğin tüm elemanları bir dizgede bir dizgiye yerleştirerek ve sonra kullanarak -split(ayırıcı olarak boşluk kullanmak en iyisidir çünkü unary -splityeterli olacaktır).
Joey

8

Dize döküm:

[string]$x

vs.

"$x"

Bunun gibi bir dizgeye döküm yapmak, dizeleri birleştirmek yerine bir dizgiyi düzleştirmek için de kullanılabilir:

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

vs.

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

Sayısal türe bir dize yayınlama:

[int]$x     [float]$x

vs.

+$x

Ayrıca PowerShell'in son ifadenin türünü ve uygulanacak dönüştürmeleri belirlemek için her zaman sol işlenenin türünü aldığını bilmek çok yararlıdır :

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

hangi gereksiz parçaların nerede olduğunu belirlemeye yardımcı olabilir.


6

Her zaman bir parametrenin tam adını girmeniz gerekmediğini ve bazı parametrelerin konumsal olduğunu unutmayın.

Get-Random -InputObject (0..10)

... kesilebilir ...

Get-Random -I (0..10)

... çünkü "Ben", InputObjectbu komut için diğer geçerli parametrelerden benzersiz şekilde tanımlamak için yeterlidir .

Daha da kesebilirsin ...

Get-Random (0..10)

... çünkü InputObjectkonumsal bir parametredir.

Borulama, özellikle parantez ihtiyacını ortadan kaldırabildiğinde, parametre olarak nesneleri beslemekten genellikle daha kısadır. Rasgele sayı üretecimizi daha da düzeltelim ...

0..10|Get-Random

Komutu değiştiremeseniz de aynı şeyi başarmanın başka yollarını aramaya devam edin. Yukarıdaki durum için bunu yapabilirsiniz:

Get-Random 11

Veya başka bir öneri * ekleyerek :

Random 11

** Not: Get-Bir komut adından çıkmak, çalışma süresini yaklaşık% 50.000 oranında şişirebilir. Komuta yalnızca bir kez ihtiyaç duyuyorsanız fena değil, uzun döngülerde kullanmak için dikkatli olun. *

Ve işte bu, basit bir komutu boyutunun üçte birine kadar düşürür.


6

Sahte üçlü operatör. Bir ififadeden doğrudan atayabilirsiniz :

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

Ancak 2 elemanlı bir dizi kullanabilir ve dizine eklemek için testi kullanabilirsiniz. $ falsey sonuçları eleman 0 alır, $ truthy sonuçları eleman 1 alır:

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

NB. Bu gerçekten dizi indeksleme yapıyor ve bir değer test sonuçları ise edebilir tam sayıya döküm, sen dizisinin sınırları dışındaysa bir öğe için sormak ve $ boş geri almak ve yapmak gerekecektir olacak !(test)kuvvete seçenekleri tersine çevirerek sonucu bir boole yayınlayın.


İlk snippet, doğru bir şekilde hatırlarsam, sarılmasını gerekli kılan bir noktada (eski PowerShell sürümleri) çalışmadı $(). Temelde komutlardan ve ifadelerden yapılan boru hatlarının ifadeler olarak kullanılmasıyla ilgili bir ayrım vardı. Görünüşe göre şu ana kadar en azından PowerShell 5'de.
Joey

Ek olarak, dizi elemanları statik değilse, indeksleme gerçekleşmeden ve sonuç atanmadan önce hem dizi oluşturma işleminin bir parçası olarak ayrıştırılır hem de işlenir. Örneğin .
AdmBorkBork

6

Sayıyı, aksi halde dize gerektiren bir işleci argümanı olarak kullanırken, sayıyı doğrudan kullanabilirsiniz. Karşılaştırmak

...-join'0'

vs.

...-join0

İle -splitde çalışır. Argüman her zaman önce bir dizgeye dönüştürülür.


Başvuru için, bu da çalışır -replace.
AdmBorkBork

-replaceaynı zamanda maçları kaldırmak istediğiniz ikinci bir argüman olmadan da çalışır,
Joey

5

Mutlak değer

İle

$n=-123

Onun yerine

[math]::abs($n)

kullanım

$n-replace'-'

Tabii ki, parantez gerektiğinde tasarruflar iptal edilir.


Veya bir operatörün sol tarafındaki sonuca ihtiyacınız olursa ;-)
Joey

5

Hataları susturmanız gerekirse, açık değişken

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

Ancak, bu çok uzun. Daha kısa bir değişken trybloğu bir komut dosyası bloğu olarak çalıştırmak ve hataları yalnızca belirsiz bir değişkene yönlendirmektir ( $nullnormal olanı olurdu, ancak bu hala çok uzun):

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

Bu, beş değerli bayttan tasarruf eder (dünya değilse).


5

Kullanım $ofs , özel değişken değiştirme O ıkış F ield S eparator bir dizi stringifying kullanılan. Dizileri birden çok kez dizelere dönüştürmeniz gerekiyorsa kullanışlıdır.

Örneğin:

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

2nd'a 2+ n karakter kaydeder -join, burada n , ayırıcının uzunluğudur ve her biri ve sonraki her biri için 5 + n ekler -join.


1
Ne yazık ki çok nadiren kullanışlıdır (en azından şu ana kadar benim golf sahalarımda - sonunda sadece tek bir birleşime kadar uzanma eğilimindeyim).
Joey

5

Otomatik değişkenler olarak true için Boolean ve yanlış var $trueve $falseancak mantıklı değil operatörünü kullanarak benzer sonuçlar elde edebilirsiniz !ve tamsayılar 0 ve 1 (veya herhangi bir sıfır olmayan tamsayı.)

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Tüm PowerShell ifadeleri, boolean olarak değerlendirilebilir. Belirli verilerin nasıl değerlendirildiğinin farkında olduğunuz sürece, boole'lar alabilirsiniz ve bunları açıkça yayınlamanıza gerek kalmaz. Bunları yaparken LHS değerine dikkat edin.

  • 0 tamsayısı yanlıştır ve sıfır olmayan tam sayılar true olarak değerlendirilir.
  • sıfır olmayan uzunluktaki dizeler doğru ve boş ya da boş (ve kendileri boş) dizeleri yanlıştır.

Başka örnekler var ama oyuncu seçimi yaparak kolayca test edebilirsiniz.

PS C:\Users\matt> [bool]@(0)
False

1
Diğer birçok veri tipi de benzer bir duruma sahiptir. Başlatılmamış değişkenler varsayılan olarak $nullfalsey'dir. Boş dize (ve boş dize ayarlanan değişkenler) falsey. Vb, daha sonra FizzBuzz'da kullanıldığı gibi dizinin indekslenmesini bir diziye kısayol olarak (örneğin, if/ / yaparken else) kullanılabilir .
AdmBorkBork

@TimmyD Çok doğru. Kullanılması ints sadece kısadır
Mat

@TimmyD Seninkini görene kadar fizzbuzz'a cevap vermek istedim .... Bunu yenemezsin .... en azından henüz değil
Matt

Not birçok durumda aslında olmadığını gerek bir bool. Sen kullanabilirsiniz 0ve 1sadece de. Örtük dönüşümler bu konuda çok yardımcı olur (bazı operatörleri sık sık zorlayabilirsiniz).
Joey

4

Invoke-Expressionve Get-Randomayrıca argümanlar yerine pipeline girişi alabilir.

Bunun için iexparantezlerin bazı ifadelere kaydedilmesini sağlar:

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

Bu durumda, randomortak bir durumun biraz optimize edilmesine izin verir:

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

İkinci kullanım şekli basitçe listeden bir öğeyi seçer. -cArgümanı bir seçim daha fazla izin verilebilir.


4

İşlevleri kullanmak yerine, tekrarlanan kod bloklarını değişkenlere kaydetmeyi düşünün.

Bunu, Rock, Paper, Scissors uygulamamda bazı karakterleri kaydetmek için kullanacaktım, bu fonksiyonu, değişkeni bile gereksiz hale getiren bir değişken olarak yeniden yazdım. Bu, aslında aynı kodu birkaç kez çalıştırdığınız yerlerde, diğer komut dosyaları için de yararlı olabilir.

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

vs.

$Hi={echo 'Hello, World!'};&$Hi

2
Argüman almayan işlevler için kullanışlıdır. Aksi halde, params(...)fonksiyon tanımlamasından daha fazla yer kaplar. İlgili: Kullanım filterüzerinde functionbunu yapabilirsiniz zaman.
Joey

İhtiyaçtan $argskaçınmak için kullanabilirsiniz params; yani $x={$args[0]+2}(veya hatta $x={2+"$args"}); Bazı durumlarda bir karakteri veya 2'yi kaydedebilir. Bunu birden fazla $x={$a,$b=$args;$a+$b+3}
param

4

Bunun $s|% t*yyerine [char[]]$sbir dizgeyi karakter dizisine bölmek için kullanabilirsiniz . TessellatingHeckler'in cevabı göz önüne alındığında : eşdeğeri % t*ygenişler | ForEach-Object -Method ToCharArray. nın-nin"$args".ToCharArray()

Örneğin, karşılaştır

$s|% t*y

ve

[char[]]$s

ve

$s.ToCharArray()

Bu birlikte yararlıdır $argsözellikle:$args|% t*y


1
Bu oldukça temiz. Bu %hileyi üyeler için de birkaç kez kullandım, ancak golf oyunlarımın çoğu bu özelliği ;-). Bu da oldukça genel bir tekniktir: İhtiyacınız olan özellik / yöntemle eşleşen (ve gerçek olandan daha kısa olan) bir harf / joker karakter kombinasyonu bulmaya çalışın.
Joey,

Cevaptan bir başka yararlı örnek: $s|% *periçin $s.toUpper()ve $s|% *weriçin $s.toLower(). Oldukça temiz olduğuna katılıyorum.
mazzy,

Bir örnek daha : |% t* "ddd\:hh\:mm\:ss"için[TimeSpan].toString("ddd\:hh\:mm\:ss")
Mazzy

Öyleyse, bu sadece bir teklif kaybıdır; onlara burada ihtiyacınız yok :-)
Joey,


3

Döngüdeki if-counters yerine Boolean mantığı kullanın

1'den 10'a kadar olan tüm çiftleri eklediğinizi varsayalım. 2+4+6+8+10=30

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

Boole olumsuzlamasını, kısaltmak için kullanabilirsiniz.

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

Bir bayttan tasarruf etmek, ancak bunun yerine Boolean'ların örtük dökümünü inçlere kullanmak ve koşulu akümülatöre döndürmek nasıl olur

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

Bu örnekte 6 bayt kaydeder.


2
İsa aşkına. Bunu işyerindeki üretim kodumda yapmayı düşünüyorum, meslektaşlarım beni bunun için sevecek.
Chavez

3

Kayan noktalı sayıların PowerShell'deki tam sayılara dönüştürülmesi bir mayın tarlasının bir parçasıdır. Varsayılan olarak dönüşüm, her zaman ondalık basamak kesmeyen ve küçük tam sayıyı bırakmayan Bankers Yuvarlama işlemini gerçekleştirir ya da her zaman yuvarlak olan 5 gibi bir sonraki sayıya kadar yuvarlar. şaşırtıcı olmak, örneğin

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

ve codegolf hesaplamaları kırmak. Diğer birçok yaygın dilde dilimleme, bu nedenle golf soruları genellikle dilimleme gerektirir. Bir [Math]::Floor()sonraki en iyi şey olarak ulaşabilirsiniz , ancak bunun yalnızca pozitif sayılar için kesilmesiyle aynı şekilde davrandığına dikkat edin, ancak negatif sayıları daha düşük - sıfırdan uzağa götürür. [Math]::Truncate()PS davranışını diğer dillerin varsayılan yuvarlamalarıyla aynı hizaya getirmeniz gerekiyor, ancak çok fazla karakter var.

Regex, ondalık noktasından sonra basamağın değiştirilmesi birkaç karakterin kaydedilmesine yardımcı olabilir:

[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

3

Bir diziyi ters çevirme

Çıktının bir şekilde yansıtıldığı birçok ilginç mücadelesinde kullanışlıdır .

Varsayalım

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

Geleneksel tersine çevirme yöntemi uzun ve sıkıcıdır ve derhal kullanım için diziyi boru hattında bırakmaz.

[array]::reverse($a)

Doğrudan diziye dizinin tersi sırayla dizilmesi, sonuçları boru hattında bıraktığı için birkaç bayttan tasarruf sağlar, ancak yine de oldukça uzundur:

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

Bunun yerine, bir döngü deneyin

$a|%{$a[-++$i]}

Ters endeksleme sayım için bir üst sınır varken iyi çalışıyor
Joey

3

PowerShell Core 6 ile başlayarak, karakter aralıkları da kullanabilirsiniz:

'a'..'z'

çok daha hantal yerini alabilir

0..25|%{[char]($_+97)}

Oh, bu çok işe yarayacak.
AdmBorkBork

1
[char[]](65..90)aynı zamanda alfabeyi oluşturmak için kullanışlı bir yoldur
Veskah
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.