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 .
code-golf
tips
powershell
Joey
sumber
sumber
Jawaban:
Kekuatan 10 literal dengan notasi ilmiah:
Kekuatan 2 liter:
Bisa berguna.
sumber
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-Object
melalui%
alih-alih menggunakanfor
.for($x=1;$x-le10;$x++){
...}
vs.
1..10|%{
...}
sumber
Anda dapat melewatkan banyak spasi di PowerShell. Jika rasanya tidak diperlukan, kemungkinan besar tidak. Ini sangat berguna dalam perbandingan.
Contoh:
vs.
Jika Anda perlu melakukan percabangan skrip Anda berdasarkan hasil dari satu pengujian yang mungkin memiliki banyak hasil,
switch
kadang-kadang dapat mencocokkan atau mengalahkan pernyataan if.Contoh (beralih vs. jika / lain - dasi):
vs.
Atau (beralih vs. jika / elseif / else - beralih menang dengan 15):
vs.
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.)
Jika Anda akan sering menggunakan perintah tertentu, terutama yang tanpa alias tangan pendek yang sudah ada sebelumnya, atur alias satu karakter sejak awal.
Contoh:
vs.
sumber
('even','odd')[$x%2]
FYI.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:
Alih-alih ini:
Anda dapat mengatur $ h dan mengeluarkannya dengan ini:
Alih-alih ini:
sumber
($x=New-Object Windows.Forms.Form).Controls.Add($t)
Switch dapat bertindak seperti loop, saat diberi array. Sebagai contoh:
Akan menampilkan:
Saya tidak sepenuhnya yakin di mana ini akan berguna, tetapi saya berharap ini akan berguna untuk seseorang suatu saat.
sumber
ForEach-Object
danswitch
dalam 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.switch -File $path
bagiGanti
[math]::pow
dengan multiplikasi. Dari padakamu bisa menulis
Ini berfungsi untuk eksponen bilangan bulat> = 0.
sumber
iex
... Alias untukInvoke-Expression
Operator pembanding mengerjakan pengumpulan nilai dengan mengembalikan nilai yang cocok:
akan menghasilkan
3
,4
dan5
. Dalam beberapa kasus ini dapat membantu menghemat lebih lama|?{$_...}
.-match
adalah operator pembanding juga.sumber
1..5-gt2
Gunakan alias jika memungkinkan. Ada banyak yang berguna:
sumber
Ingin menemukan maksimum atau minimum dari kumpulan nilai? Mencoba
atau
sudah?
Cukup urutkan dan gunakan item terakhir atau pertama:
sumber
0
,1
,2
,3
,4
,5
,6
,7
,8
atau9
, itu akan menghemat byte untuk menulis panjang diketahui bukan-1
.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.Dengan properti seperti
.Length
kita tidak dapat menggunakan sihir v3 yang biasanya bekerja pada array karenaLength
merupakan properti dari array itu sendiri, sehingga dua di atas dapat digunakan untuk mendapatkan panjang anggota individu. Theselect
datang dalam sedikit memagut lebih pendek.Tetapi
%
dapat mengambil nama properti secara langsung dan mengembalikan nilai itu: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.Tetapi tergantung pada apa yang Anda lakukan dengan ini, ini bisa lebih buruk. Anda dapat melakukannya
$a.Length*5
selain 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):Dengan argumen:
Ini tidak sepenuhnya sama di mana
-replace
operator 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 menggunakanWhere-Object
pendekatan standar scriptblock jika nama properti cukup panjang dan unik.sumber
.ToString()
!Menemukan jumlah jauh:
Cara yang lebih pendek:
Dan bahkan lebih pendek:
sumber
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).
sumber
Kata
Get
kerja tersirat. Ini bisa dipersingkatGet-Frob
menjadi adilFrob
. Pesaing yang sering adalahdate
ataurandom
.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:sumber
nal g Get-Random
untuk menyimpan karakter nanti. Mengubahnyanal g Random
menyebabkan 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).Measure-Command
doa singkat (100 kaliGet-Random
vs.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).Get-Variable
vsgv
dan mendapat perbandingan yang serupa.Get-
. Itu adalah mengasapi waktu berjalan yang sangat degil untuk penghematan hanya 4 karakter panjangnya.for
loop dapat memiliki apa saja antara 0 dan tiga pernyataan di header mereka:Loop tak berujung:
Loop dengan inisialisasi:
Loop dengan inisialisasi dan kondisi akhir:
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
while
sedikit lebih pendek. Membandingkandan
Dengan bonus tambahan yang dapat Anda tempel di baris sebelumnya (jika ada) ke dalam
for
juga tanpa biaya tambahan (dan bahkan menghemat karakter).sumber
Jika Anda menetapkan larik yang Anda tahu hanya akan memiliki dua nilai, jangan gunakan pengindeksan.
Sesuatu seperti ini:
Dapat dengan mudah diubah menjadi ini:
Ini juga bisa berguna jika Anda hanya perlu elemen pertama dari sebuah array:
sumber
$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-split
akan cukup).Casting ke string:
vs.
Casting ke string seperti ini juga dapat digunakan untuk meratakan array string, bukannya bergabung:
vs.
Casting string ke tipe numerik:
vs.
Juga sangat berguna untuk mengetahui bahwa PowerShell selalu menggunakan tipe operan kiri untuk menentukan tipe akhir dari ekspresi dan konversi yang akan diterapkan:
yang dapat membantu menentukan di mana pemain tidak perlu berada.
sumber
Jangan lupa bahwa Anda tidak selalu perlu memberikan nama lengkap suatu parameter, dan beberapa parameter bersifat posisional.
... dapat dipangkas menjadi ...
... karena "I", dalam hal ini, cukup untuk mengidentifikasi secara unik
InputObject
dari parameter lain yang valid untuk perintah ini.Anda bisa memotongnya lebih jauh ke ...
... karena
InputObject
merupakan 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 ...
Juga cari cara lain untuk mencapai hal yang sama, bahkan jika Anda tidak dapat mengubah perintah. Untuk kasus di atas, Anda bisa melakukan ini:
Atau, memasukkan saran lain *:
** 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.
sumber
Operator ternary palsu. Anda dapat menetapkan langsung dari
if
pernyataan:Tapi Anda bisa menggunakan array 2-elemen dan menggunakan tes untuk mengindeks ke dalamnya. $ hasil falsey mendapatkan elemen 0, $ hasil benar mengambil elemen 1:
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.sumber
$()
. Pada dasarnya ada perbedaan menggunakan pipa yang dibuat dari perintah dan pernyataan sebagai ekspresi. Sepertinya sudah hilang sekarang, setidaknya di PowerShell 5.Saat menggunakan nomor sebagai argumen ke operator yang membutuhkan string, Anda dapat menggunakan nomor tersebut secara langsung. Membandingkan
vs.
Bekerja dengan
-split
baik juga. Argumen selalu dikonversi ke string terlebih dahulu.sumber
-replace
baik.-replace
juga berfungsi tanpa argumen kedua saat Anda ingin menghapus pertandingan,Nilai mutlak
Dengan
Dari pada
menggunakan
Tentu saja, penghematan dibatalkan jika tanda kurung diperlukan.
sumber
Jika Anda perlu membungkam kesalahan, varian yang jelas adalah
Namun, ini terlalu lama. Varian yang lebih pendek adalah menjalankan
try
blok sebagai blok skrip dan hanya mengarahkan kesalahan ke variabel yang tidak disetel ($null
akan menjadi yang biasa, tetapi itu masih terlalu lama):Ini menghemat lima byte berharga (jika bukan dunia).
sumber
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:
Menyimpan 2+ n karakter pada tanggal 2
-join
, di mana n adalah panjang pemisah, dan menyimpan 5+ n tambahan untuk karakter ke-3-join
dan masing-masing sesudahnya.sumber
Variabel otomatis memiliki boolean untuk True dan False sebagai
$true
dan$false
tetapi Anda bisa mendapatkan hasil yang sama menggunakan operator bukan logis!
dan bilangan bulat 0 dan 1 (atau bilangan bulat bukan nol).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.
Ada contoh lain tetapi Anda dapat dengan mudah menguji dengan melakukan gips
sumber
$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 melakukanif
/else
), seperti yang digunakan dalam FizzBuzz .int
s hanya lebih pendekbool
. Anda bisa menggunakan0
dan1
juga. Konversi tersirat banyak membantu dalam hal itu (yang sering Anda paksa dengan operator tertentu).Invoke-Expression
danGet-Random
juga bisa mendapatkan input pipa bukannya argumen.Untuk
iex
ini, Anda dapat menyimpan tanda kurung pada beberapa ekspresi:Dalam hal
random
ini memungkinkan kasus umum dioptimalkan sedikit:Cara terakhir menggunakannya hanya memilih item dari daftar. The
-c
argumen dapat diberikan untuk memungkinkan lebih dari pilihan tunggal.sumber
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.
vs.
sumber
params(...)
akan mengambil lebih banyak ruang daripada menyimpan definisi fungsi. Terkait: Gunakanfilter
lebih darifunction
saat Anda bisa melakukannya.$args
untuk menghindari kebutuhanparams
; 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}
Anda dapat menggunakan
$s|% t*y
sebagai gantinya[char[]]$s
untuk membagi string menjadi char array. Diberikan dari jawaban TessellatingHeckler :% t*y
memperluas ke| ForEach-Object -Method ToCharArray
equiv. dari"$args".ToCharArray()
Sebagai contoh, bandingkan
dan
dan
Ini berguna
$args
terutama:$args|% t*y
sumber
%
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).$s|% *per
untuk$s.toUpper()
dan$s|% *wer
untuk$s.toLower()
. Saya setuju itu cukup rapi.|% t* "ddd\:hh\:mm\:ss"
untuk[TimeSpan].toString("ddd\:hh\:mm\:ss")
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
Anda bisa menggunakan negasi Boolean untuk mempersingkatnya
untuk menyimpan byte, tetapi bagaimana kalau alih-alih menggunakan casting implisit Boolean ke int, dan roll kondisional ke akumulator
Menghemat 6 byte dalam contoh ini.
sumber
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
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:
sumber
Membalikkan array
Sangat berguna dalam banyak tantangan ascii-art di mana output tercermin dalam beberapa mode.
Misalkan Anda punya
Metode pembalikan tradisional panjang, membosankan, dan tidak meninggalkan array pada pipa untuk segera digunakan.
Pengindeksan langsung ke dalam array dalam urutan terbalik menghemat beberapa byte, karena meninggalkan hasil pada pipeline, tetapi masih agak lama:
Sebagai gantinya, coba satu lingkaran
sumber
Dimulai dengan PowerShell Core 6, Anda juga dapat menggunakan rentang untuk karakter:
yang dapat menggantikan yang jauh lebih rumit
sumber
[char[]](65..90)
juga merupakan cara praktis untuk menghasilkan alfabet