Kiat untuk bermain golf di PowerShell

45

Apa tips umum yang Anda miliki untuk bermain golf di Windows PowerShell? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk PowerShell (mis. "Hapus komentar" bukan jawaban). Silakan kirim satu tip per jawaban.

- diambil hampir kata demi kata dari pertanyaan marcog .

Joey
sumber
3
Ketika saya googled "golf PowerShell" ini adalah hit pertama!
Matt

Jawaban:

24

Kekuatan 10 literal dengan notasi ilmiah:

4e6 = 4000000

Kekuatan 2 liter:

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

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

Bisa berguna.

Joey
sumber
19

Jika Anda perlu menjalankan loop, dan Anda tahu persis berapa kali harus dijalankan setiap kali, pertimbangkan untuk memipis array array yang berdekatan ke alias ForEach-Objectmelalui %alih-alih menggunakan for.

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

vs.

1..10|%{...}

Iszi
sumber
18

Anda dapat melewatkan banyak spasi di PowerShell. Jika rasanya tidak diperlukan, kemungkinan besar tidak. Ini sangat berguna dalam perbandingan.

Contoh:

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

vs.

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

Jika Anda perlu melakukan percabangan skrip Anda berdasarkan hasil dari satu pengujian yang mungkin memiliki banyak hasil, switchkadang-kadang dapat mencocokkan atau mengalahkan pernyataan if.

Contoh (beralih vs. jika / lain - dasi):

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

vs.

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

Atau (beralih vs. jika / elseif / else - beralih menang dengan 15):

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

vs.

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

Jika sakelar sebenarnya berdasarkan hasil matematika tertentu, seperti operasi modulo di atas, Anda dapat mengganti sakelar sepenuhnya dengan array. Di sini, ia menyimpan 13 karakter lain dan bahkan lebih pendek dari pernyataan dua opsi asli jika / selain itu. (Terima kasih kepada Danko Durbic untuk bagian ini.)

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

Jika Anda akan sering menggunakan perintah tertentu, terutama yang tanpa alias tangan pendek yang sudah ada sebelumnya, atur alias satu karakter sejak awal.

Contoh:

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

vs.

Get-Random 10;Get-Random 10;Get-Random 10
Iszi
sumber
('even','odd')[$x%2]FYI.
TheIncorrigible1
15

Enkapsulasi perintah yang mendefinisikan variabel dalam tanda kurung memungkinkan Anda untuk memberi makan definisi variabel langsung ke perintah lain.

Misalnya, Anda dapat menetapkan $ x dan kemudian menetapkan $ y berdasarkan nilai $ x dalam satu kesempatan dengan ini:

$y=($x=1)+1

Alih-alih ini:

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

Anda dapat mengatur $ h dan mengeluarkannya dengan ini:

($h='Hello World!')

Alih-alih ini:

$h='Hello World!';$h
Iszi
sumber
1
Ini sangat berguna untuk memanggil metode pada objek. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD
14

Switch dapat bertindak seperti loop, saat diberi array. Sebagai contoh:

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

Akan menampilkan:

FOO
BAR
MEH

Saya tidak sepenuhnya yakin di mana ini akan berguna, tetapi saya berharap ini akan berguna untuk seseorang suatu saat.

Iszi
sumber
2
Ini berguna setiap kali Anda membutuhkan ForEach-Objectdan switchdalam itu. Ini misalnya (dalam dunia nyata) kode yang sangat bagus untuk menulis parser cepat dari file teks di mana Anda perlu melakukan hal-hal yang berbeda tergantung pada regex mana yang cocok.
Joey
Ini ... sangat aneh. Array seharusnya tidak cocok dengan char, tetapi itu cocok.
kucing
@Joey Itu ini apa switch -File $pathbagi
TheIncorrigible1
Tidak semua yang diurai menjadi file.
Joey
12

Ganti [math]::powdengan multiplikasi. Dari pada

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

kamu bisa menulis

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

Ini berfungsi untuk eksponen bilangan bulat> = 0.

Danko Durbić
sumber
Saya perlu melihat jawaban ini untuk memahami iex... Alias ​​untukInvoke-Expression
HeatfanJohn
11

Operator pembanding mengerjakan pengumpulan nilai dengan mengembalikan nilai yang cocok:

1..5 -gt 2

akan menghasilkan 3, 4dan 5. Dalam beberapa kasus ini dapat membantu menghemat lebih lama |?{$_...}.

-match adalah operator pembanding juga.

Joey
sumber
1
Perhatikan bahwa Anda tidak memerlukan spasi dalam contoh itu1..5-gt2
Matt
1
Aku tahu; ini lebih tentang menunjukkan tekniknya. Spasi berada dalam jawaban terpisah .
Joey
11

Gunakan alias jika memungkinkan. Ada banyak yang berguna:

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

Ingin menemukan maksimum atau minimum dari kumpulan nilai? Mencoba

(...|measure -ma).Maximum

atau

(...|measure -mi).Minimum

sudah?

Cukup urutkan dan gunakan item terakhir atau pertama:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
Joey
sumber
1
Dan, jika Anda tahu panjang pengumpulan nilai dan itu kurang dari 10 ...
wizzwizz4
@ wizzwizz4: Oh, panjang maksimum sering dapat digunakan secara kreatif, tidak harus 10. Meskipun untuk kasus khusus ini saya tidak ingat contoh di mana itu pernah membantu.
Joey
1
Maksudku, jika item akhir diketahui 0, 1, 2, 3, 4, 5, 6, 7, 8atau 9, itu akan menghemat byte untuk menulis panjang diketahui bukan -1.
wizzwizz4
10

Memperpendek Nama Properti

Sayangnya, tidak seperti parameter, properti / metode (apa pun yang diakses dengan titik .) biasanya tidak dapat disingkat menjadi bentuk yang tidak ambigu.

Tetapi cmdlet tertentu dapat beroperasi pada nama properti dan mengambil wildcard, dan ada set parameter yang sedikit diketahui %dan ?yang dapat berguna.

Biasanya kami meneruskan blokir skrip dan merujuk ke item dengan $_, tetapi ada bentuk lain dari ini yang mengambil nama properti, dan menerima wildcard.

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

Dengan properti seperti .Lengthkita tidak dapat menggunakan sihir v3 yang biasanya bekerja pada array karena Lengthmerupakan properti dari array itu sendiri, sehingga dua di atas dapat digunakan untuk mendapatkan panjang anggota individu. The selectdatang dalam sedikit memagut lebih pendek.

Tetapi %dapat mengambil nama properti secara langsung dan mengembalikan nilai itu:

$a|% Length

Yang bisa disingkat dengan wildcard. Wildcard harus menyelesaikan ke satu properti (atau metode, lebih lanjut tentang itu nanti), jadi itu akan melemparkan kesalahan bermanfaat jika tidak, menunjukkan dengan tepat anggota mana yang bisa diatasi.

Dalam kasus Length, Le*biasanya yang terpendek. Bahkan pada string tunggal, metode ini lebih pendek 1 byte daripada hanya menggunakan properti.

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

Tetapi tergantung pada apa yang Anda lakukan dengan ini, ini bisa lebih buruk. Anda dapat melakukannya $a.Length*5selain melakukannya dengan ekspresi pipeline yang harus Anda bungkus ($a|% Le*)*5; mungkin masih layak jika itu melawan array, tapi intinya itu tidak selalu tepat sebagai pengganti langsung.

Ini bekerja dengan metode juga, dan Anda dapat meninggalkan ()yang membuat nama lengkap dengan panjang yang sama, tetapi pembatasan yang sama seperti di atas tentang kadang-kadang harus membungkusnya. Metode ini harus memiliki kelebihan yang tidak memerlukan parameter (Anda dapat melewatkan argumen dengan menempatkannya setelah nama metode, yang sangat bagus):

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

Dengan argumen:

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

Ini tidak sepenuhnya sama di mana -replaceoperator melakukan penggantian regex, tetapi jika Anda hanya melakukan penggantian string, itu bisa (sekarang) lebih pendek untuk menggunakan metode ini; ini membantu bahwa string adalah argumen cmdlet bukan argumen metode sehingga tidak perlu dikutip.

Properties Dimana-Obyek

?dapat mengambil (sebagian) nama properti juga, dan menerapkan "operator" untuk itu (dalam bentuk parameter sakelar). Sekali lagi ini bisa lebih pendek daripada menggunakan Where-Objectpendekatan standar scriptblock jika nama properti cukup panjang dan unik.

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

($a|% Le*)-gt5           # 14 - Lengths, not objs
briantis
sumber
1
Salah satu dari sedikit tempat di mana spasi putih diperlukan. Nice menemukan. Saya dapat memikirkan beberapa area di mana ini akan mempersingkat hal-hal.
AdmBorkBork
Sunting Joey yang bagus! Terima kasih.
briantist
Menemukan Anda cara untuk membuatnya lebih pendek ;-) ... Yang menyedihkan tentang ini adalah bahwa secara keseluruhan itu pipa lagi, yang membatasi kegunaannya sedikit. Atau lebih tepatnya, ada banyak tempat di mana Anda harus membungkusnya menjadi tanda kurung lagi untuk mendapatkan ekspresi. Tetapi beberapa teknik golf tanpa pertukaran ...
Joey
1
@ConnorLSW ah ya saya bermaksud memperbarui ini karena saya sudah menyadari Anda dapat melewati argumen seperti itu, yang sangat meningkatkan kegunaannya Penggunaan hebat .ToString()!
briantist
2
@ Briantist, ini telah mengubah PowerShell menjadi bahasa yang jauh lebih kompetitif, benar-benar memotong beberapa panggilan .Net yang berbelit-belit.
colsw
9

Menemukan jumlah jauh:

(...|measure -s).Sum

Cara yang lebih pendek:

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

Dan bahkan lebih pendek:

...-join'+'|iex
Joey
sumber
9

Titik koma dan jeda baris dapat dipertukarkan. Kode golf seringkali lebih mudah dibaca jika tidak dimasukkan ke dalam satu baris. Dan panjangnya masih sama (asalkan Anda menggunakan U + 000A sebagai jeda baris yang ditangani PowerShell tanpa masalah).

Joey
sumber
2
Tunggu, kami khawatir tentang keterbacaan ?!
Kevin Cox
4
Jika tidak berpengaruh pada panjangnya ... mengapa tidak?
Joey
Bukankah secara teknis ada bedanya karena titik koma adalah satu karakter yang kurang dari \ r \ n? Hanya di Unix itu adalah singular \ n.
Vasili Syrakis
2
@Vasili: Anda dapat menyimpan file dengan baik dengan hanya U + 000A yang tersirat. PowerShell tidak akan mengeluh. Yang saya tulis dalam jawaban sudah, by the way. Jeda baris adalah properti file , bukan sistem operasi yang digunakannya. Tidak ada yang mengatakan bahwa Anda tidak dapat menggunakan ujung jalur Unix pada Windows.
Joey
@ Joey Jika Anda telah menggunakan instalasi baru Windows untuk melakukan pemrograman cepat, Anda akan melihat bahwa Notepad tidak cocok dengan \ x0a
Stan Strum
9

Kata Getkerja tersirat. Ini bisa dipersingkat Get-Frobmenjadi adil Frob. Pesaing yang sering adalah dateatau random.

Perhatikan bahwa ini tidak akan berfungsi dengan baik dalam beberapa kasus karena Anda mungkin memiliki utilitas GNU di jalur Anda (atau program asli lainnya yang berbenturan). Urutan pencarian perintah dalam kasus itu tampaknya lebih memilih program asli sebelum mempertimbangkan cmdlet dengan yang Get-dihapus:

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
sumber
Ini tidak cukup selalu berhasil seperti yang diharapkan. Saya memiliki skrip yang dimulai dengan nal g Get-Randomuntuk menyimpan karakter nanti. Mengubahnya nal g Randommenyebabkan skrip untuk menggantung tanpa batas waktu (atau, setidaknya, mengambil jumlah waktu yang terlalu banyak untuk diproses - saya belum memiliki kesabaran untuk menunggu sampai akhir, tetapi butuh beberapa kali lipat lebih lama dari bentuk aslinya sebelum saya batalkan).
Iszi
2
Dua Measure-Commanddoa singkat (100 kali Get-Randomvs. random) katakan padaku ini 500 kali lebih lambat. Aku tidak tahu itu sebelumnya, jujur ​​saja. Tapi itu baik untuk diingat, terutama dalam loop dengan banyak iterasi. Yang sedang berkata, kode golf harus pendek, tidak cepat ( yang dikatakan, itu menyebalkan harus menunggu dua hari untuk jawaban untuk masalah Project Euler).
Joey
1
Masalah saya menjalankan 10.000 iterasi skenario Monty Hall masing-masing membutuhkan tiga iterasi Get-Random. Peningkatan waktu pemrosesan 50.000%, dikalikan di 30.000 proses cukup buruk.
Iszi
Wow. Sepertinya hal yang sama mungkin berlaku untuk alias apa pun. Diuji Get-Variablevs gvdan mendapat perbandingan yang serupa.
Iszi
1
Itu mungkin saja. Saya melakukan beberapa matematika dan menganggap skrip Monty Hall saya akan memakan waktu sekitar 1,5 jam (biasanya, 10-11 detik) untuk berjalan tanpa Get-. Itu adalah mengasapi waktu berjalan yang sangat degil untuk penghematan hanya 4 karakter panjangnya.
Iszi
8

for loop dapat memiliki apa saja antara 0 dan tiga pernyataan di header mereka:

Loop tak berujung:

for(){}

Loop dengan inisialisasi:

for($n=0){}

Loop dengan inisialisasi dan kondisi akhir:

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

Dalam kasus seperti itu, titik koma tambahan di akhir dapat dihilangkan (secara eksplisit dinyatakan dalam spesifikasi bahasa , jadi ini bukan detail implementasi) berbeda dengan bahasa mirip-C yang selalu membutuhkan tepat tiga pernyataan.

Ini juga membuat whilesedikit lebih pendek. Membandingkan

while(...){}

dan

for(;...){}

Dengan bonus tambahan yang dapat Anda tempel di baris sebelumnya (jika ada) ke dalam forjuga tanpa biaya tambahan (dan bahkan menghemat karakter).

Joey
sumber
8

Jika Anda menetapkan larik yang Anda tahu hanya akan memiliki dua nilai, jangan gunakan pengindeksan.

Sesuatu seperti ini:

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

Dapat dengan mudah diubah menjadi ini:

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

Ini juga bisa berguna jika Anda hanya perlu elemen pertama dari sebuah array:

$a,$b=1..10
$a # 1
$b # 2..10
SomeShinyMonica
sumber
Dalam hal ini (dengan string) $a="apple";$o="orange"panjangnya identik. Ini adalah array yang lebih panjang yang kadang-kadang dapat dioptimalkan dengan cukup baik, misalnya dengan meletakkan semua elemen dalam sebuah string dengan pemisah dan kemudian menggunakan -split(terbaik untuk menggunakan spasi putih sebagai pemisah karena dengan demikian unary -splitakan cukup).
Joey
8

Casting ke string:

[string]$x

vs.

"$x"

Casting ke string seperti ini juga dapat digunakan untuk meratakan array string, bukannya bergabung:

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

vs.

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

Casting string ke tipe numerik:

[int]$x     [float]$x

vs.

+$x

Juga sangat berguna untuk mengetahui bahwa PowerShell selalu menggunakan tipe operan kiri untuk menentukan tipe akhir dari ekspresi dan konversi yang akan diterapkan:

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

yang dapat membantu menentukan di mana pemain tidak perlu berada.

Joey
sumber
6

Jangan lupa bahwa Anda tidak selalu perlu memberikan nama lengkap suatu parameter, dan beberapa parameter bersifat posisional.

Get-Random -InputObject (0..10)

... dapat dipangkas menjadi ...

Get-Random -I (0..10)

... karena "I", dalam hal ini, cukup untuk mengidentifikasi secara unik InputObjectdari parameter lain yang valid untuk perintah ini.

Anda bisa memotongnya lebih jauh ke ...

Get-Random (0..10)

... karena InputObjectmerupakan parameter posisi.

Perpipaan biasanya lebih pendek daripada memberi makan objek sebagai parameter, terutama ketika itu dapat menghilangkan kebutuhan untuk tanda kurung. Mari kita potong generator nomor acak kami lebih lanjut ...

0..10|Get-Random

Juga cari cara lain untuk mencapai hal yang sama, bahkan jika Anda tidak dapat mengubah perintah. Untuk kasus di atas, Anda bisa melakukan ini:

Get-Random 11

Atau, memasukkan saran lain *:

Random 11

** Catatan: Menghilangkan Get-nama perintah dapat mengasapi waktu berjalan sekitar 50.000%. Tidak buruk jika Anda hanya perlu perintah sekali, tetapi hati-hati menggunakannya dalam loop panjang. *

Dan itulah cara mengetuk perintah sederhana hingga sepertiga dari ukurannya.

Iszi
sumber
6

Operator ternary palsu. Anda dapat menetapkan langsung dari ifpernyataan:

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

Tapi Anda bisa menggunakan array 2-elemen dan menggunakan tes untuk mengindeks ke dalamnya. $ hasil falsey mendapatkan elemen 0, $ hasil benar mengambil elemen 1:

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

NB. bahwa ini benar-benar melakukan pengindeksan array, dan jika tes menghasilkan nilai yang dapat dilemparkan ke integer, Anda akan meminta item di luar batas array dan mendapatkan $ null kembali, dan perlu dilakukan !(test)untuk memaksa melemparkan hasilnya ke bool, dengan opsi dibalik.

TessellatingHeckler
sumber
Cuplikan pertama tidak berfungsi pada satu titik waktu (versi PowerShell yang lebih lama), jika saya ingat dengan benar, membuatnya perlu untuk membungkusnya $(). Pada dasarnya ada perbedaan menggunakan pipa yang dibuat dari perintah dan pernyataan sebagai ekspresi. Sepertinya sudah hilang sekarang, setidaknya di PowerShell 5.
Joey
Selain itu, jika elemen array non-statis, keduanya diuraikan dan diproses sebagai bagian dari pembuatan array sebelum pengindeksan terjadi dan hasilnya ditetapkan. Sebagai contoh .
AdmBorkBork
6

Saat menggunakan nomor sebagai argumen ke operator yang membutuhkan string, Anda dapat menggunakan nomor tersebut secara langsung. Membandingkan

...-join'0'

vs.

...-join0

Bekerja dengan -splitbaik juga. Argumen selalu dikonversi ke string terlebih dahulu.

Joey
sumber
Untuk referensi, ini berfungsi dengan -replacebaik.
AdmBorkBork
-replacejuga berfungsi tanpa argumen kedua saat Anda ingin menghapus pertandingan,
Joey
5

Nilai mutlak

Dengan

$n=-123

Dari pada

[math]::abs($n)

menggunakan

$n-replace'-'

Tentu saja, penghematan dibatalkan jika tanda kurung diperlukan.

Berasal
sumber
Atau jika Anda membutuhkan hasilnya di sisi kiri operator ;-)
Joey
5

Jika Anda perlu membungkam kesalahan, varian yang jelas adalah

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

Namun, ini terlalu lama. Varian yang lebih pendek adalah menjalankan tryblok sebagai blok skrip dan hanya mengarahkan kesalahan ke variabel yang tidak disetel ( $nullakan menjadi yang biasa, tetapi itu masih terlalu lama):

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

Ini menghemat lima byte berharga (jika bukan dunia).

Joey
sumber
5

Gunakan $ofs variabel khusus untuk mengubah eparator O utput F ield S yang digunakan saat meringkas array. Berguna jika Anda perlu mengubah array menjadi string beberapa kali.

Sebagai contoh:

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

Menyimpan 2+ n karakter pada tanggal 2 -join, di mana n adalah panjang pemisah, dan menyimpan 5+ n tambahan untuk karakter ke-3 -joindan masing-masing sesudahnya.

AdmBorkBork
sumber
1
Sayangnya sangat jarang berguna (setidaknya dalam bermain golf saya sejauh ini - saya cenderung melepasnya menjadi hanya satu bergabung di akhir).
Joey
5

Variabel otomatis memiliki boolean untuk True dan False sebagai $truedan $falsetetapi Anda bisa mendapatkan hasil yang sama menggunakan operator bukan logis !dan bilangan bulat 0 dan 1 (atau bilangan bulat bukan nol).

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Dekat semua ekspresi PowerShell dapat dievaluasi sebagai booleans. Jadi selama Anda mengetahui bagaimana data tertentu dievaluasi Anda bisa mendapatkan boolean dan tidak perlu secara eksplisit melemparkannya. Waspadai nilai LHS saat melakukan ini.

  • Bilangan bulat 0 adalah bilangan bulat palsu dan bukan nol dievaluasi ke true.
  • string panjang non-nol adalah string benar dan kosong atau null (dan null sendiri) adalah palsu.

Ada contoh lain tetapi Anda dapat dengan mudah menguji dengan melakukan gips

PS C:\Users\matt> [bool]@(0)
False
Mat
sumber
1
Banyak tipe data lain juga memiliki status serupa. Variabel tidak diinisialisasi default ke $null, yaitu falsey. String kosong (dan variabel yang disetel ke string kosong) adalah falsey. Dll. Ini kemudian dapat digunakan untuk pintas pengindeksan ke dalam array (misalnya, ketika melakukan if/ else), seperti yang digunakan dalam FizzBuzz .
AdmBorkBork
@TimmyD Sangat benar. Menggunakan ints hanya lebih pendek
Matt
@ TimmyD Saya ingin menjawab fizzbuzz sampai saya melihat milikmu .... Tidak bisa mengalahkan itu ... setidaknya belum
Matt
Perhatikan bahwa dalam banyak kasus Anda tidak benar-benar membutuhkan sebuah bool. Anda bisa menggunakan 0dan 1juga. Konversi tersirat banyak membantu dalam hal itu (yang sering Anda paksa dengan operator tertentu).
Joey
4

Invoke-Expressiondan Get-Randomjuga bisa mendapatkan input pipa bukannya argumen.

Untuk iexini, Anda dapat menyimpan tanda kurung pada beberapa ekspresi:

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

Dalam hal randomini memungkinkan kasus umum dioptimalkan sedikit:

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

Cara terakhir menggunakannya hanya memilih item dari daftar. The -cargumen dapat diberikan untuk memungkinkan lebih dari pilihan tunggal.

Joey
sumber
4

Pertimbangkan untuk menyimpan blok skrip berulang dalam variabel, alih-alih menggunakan fungsi.

Saya akan menggunakan ini untuk menyimpan beberapa karakter di Rock, Paper, Gunting implementasi saya sebelum saya menyadari bahwa menulis ulang fungsi sebagai variabel membuat bahkan variabel tidak perlu. Ini masih bisa berguna untuk skrip lain, di mana Anda sebenarnya menjalankan kode yang sama beberapa kali.

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

vs.

$Hi={echo 'Hello, World!'};&$Hi
Iszi
sumber
2
Berguna untuk fungsi yang tidak mengambil argumen. Kalau tidak, params(...)akan mengambil lebih banyak ruang daripada menyimpan definisi fungsi. Terkait: Gunakan filterlebih dari functionsaat Anda bisa melakukannya.
Joey
Anda dapat menggunakan $argsuntuk menghindari kebutuhan params; yaitu $x={$args[0]+2}(atau bahkan $x={2+"$args"}); dapat menyimpan karakter atau 2 dalam beberapa keadaan. Anda juga dapat menggabungkan ini dengan trik lain untuk beberapa params:$x={$a,$b=$args;$a+$b+3}
JohnLBevan
4

Anda dapat menggunakan $s|% t*ysebagai gantinya [char[]]$suntuk membagi string menjadi char array. Diberikan dari jawaban TessellatingHeckler : % t*ymemperluas ke | ForEach-Object -Method ToCharArrayequiv. dari"$args".ToCharArray()

Sebagai contoh, bandingkan

$s|% t*y

dan

[char[]]$s

dan

$s.ToCharArray()

Ini berguna $argsterutama:$args|% t*y

mazzy
sumber
1
Cukup rapi. Saya telah menggunakan %trik untuk anggota beberapa kali juga, tetapi sebagian besar golf saya mendahului fitur itu ;-). Ini juga merupakan teknik yang cukup umum: Cobalah menemukan kombinasi huruf / wildcard yang cocok dengan properti / metode yang Anda butuhkan (dan lebih pendek daripada yang asli).
Joey
Contoh lain yang bermanfaat dari jawabannya: $s|% *peruntuk $s.toUpper()dan $s|% *weruntuk $s.toLower(). Saya setuju itu cukup rapi.
mazzy
Satu lagi contoh : |% t* "ddd\:hh\:mm\:ss"untuk[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy
Nah, itu hanya buang-buang kutipan saja; Anda tidak membutuhkannya di sini :-)
Joey
3

Gunakan logika Boolean sebagai ganti if-counter dalam satu loop

Misalkan Anda menambahkan semua angka genap dari 1 hingga 10 ... 2+4+6+8+10=30

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

Anda bisa menggunakan negasi Boolean untuk mempersingkatnya

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

untuk menyimpan byte, tetapi bagaimana kalau alih-alih menggunakan casting implisit Boolean ke int, dan roll kondisional ke akumulator

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

Menghemat 6 byte dalam contoh ini.

AdmBorkBork
sumber
2
Yesus Kristus. Saya berencana melakukan ini dalam kode produksi saya di tempat kerja, kolega saya akan menyukai saya karenanya.
Chavez
3

Mengubah angka floating-point ke bilangan bulat di PowerShell adalah sedikit ladang ranjau. Secara default, konversi melakukan Bankir Rounding yang tidak selalu memotong desimal dan meninggalkan angka keseluruhan yang lebih kecil, atau selalu membulatkan 0,5 hingga ke angka berikutnya seperti yang dilakukan orang dengan biasa, itu membulatkan genap satu arah dan peluang dengan cara lain - ini dapat mengejutkan, misalnya

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

dan hancurkan perhitungan codegolf. Banyak bahasa umum lainnya melakukan pembulatan pemotongan, oleh karena itu pertanyaan golf seringkali memerlukan pemotongan. Anda mungkin meraih [Math]::Floor()sebagai hal terbaik berikutnya, tetapi waspadalah ini hanya berperilaku sama dengan pemotongan untuk angka positif, tetapi itu mengambil angka negatif lebih rendah - lebih jauh dari nol. [Math]::Truncate()adalah apa yang Anda butuhkan untuk membawa perilaku PS sejalan dengan pembulatan default bahasa lain, tetapi banyak karakter.

Regex yang mengganti digit setelah titik desimal dapat membantu menyelamatkan beberapa karakter:

[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
sumber
3

Membalikkan array

Sangat berguna dalam banyak tantangan mana output tercermin dalam beberapa mode.

Misalkan Anda punya

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

Metode pembalikan tradisional panjang, membosankan, dan tidak meninggalkan array pada pipa untuk segera digunakan.

[array]::reverse($a)

Pengindeksan langsung ke dalam array dalam urutan terbalik menghemat beberapa byte, karena meninggalkan hasil pada pipeline, tetapi masih agak lama:

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

Sebagai gantinya, coba satu lingkaran

$a|%{$a[-++$i]}
AdmBorkBork
sumber
pengindeksan terbalik berfungsi dengan baik ketika ada batas atas untuk penghitungan
Joey
3

Dimulai dengan PowerShell Core 6, Anda juga dapat menggunakan rentang untuk karakter:

'a'..'z'

yang dapat menggantikan yang jauh lebih rumit

0..25|%{[char]($_+97)}
Joey
sumber
Oh, ini akan sangat berguna.
AdmBorkBork
1
[char[]](65..90)juga merupakan cara praktis untuk menghasilkan alfabet
Veskah