Ini adalah perintah perlfaq4 yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa stasiun kerja online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS
PROGRAM:
NAMA
perlfaq4 - Manipulasi Data
VERSION
versi 5.021009
DESKRIPSI
Bagian FAQ ini menjawab pertanyaan yang berkaitan dengan memanipulasi angka, tanggal, string,
array, hash, dan berbagai masalah data.
Tanggal: Bilangan
Mengapa am I mendapatkan panjang desimal (misalnya, 19.9499999999999) sebagai gantinya of itu nomor I harus be
mendapatkan (misalnya, 19.95)?
Untuk penjelasan panjangnya, lihat "Apa yang Harus Diketahui Setiap Ilmuwan Komputer" dari David Goldberg
Tentang Aritmatika Titik-Mengambang"
(<http://web.cse.msu.edu/~cse320/Documents/FloatingPoint.pdf>).
Secara internal, komputer Anda mewakili angka floating-point dalam biner. Digital (seperti dalam
kekuatan dua) komputer tidak dapat menyimpan semua angka dengan tepat. Beberapa bilangan real kalah
presisi dalam prosesnya. Ini adalah masalah dengan bagaimana komputer menyimpan nomor dan mempengaruhi
semua bahasa komputer, bukan hanya Perl.
perlnumber menunjukkan detail mengerikan dari representasi angka dan konversi.
Untuk membatasi jumlah tempat desimal dalam angka Anda, Anda dapat menggunakan "printf" atau
fungsi "sprintf". Lihat "Aritmatika titik-mengambang" di perlop untuk lebih jelasnya.
printf "%.2f", 10/3;
$angka saya = sprintf "%.2f", 10/3;
Mengapa is ke dalam() rusak?
"int()" Anda kemungkinan besar berfungsi dengan baik. Ini adalah angka yang tidak cukup
menurutmu.
Pertama, lihat jawaban untuk "Mengapa saya mendapatkan desimal yang panjang (mis., 19.9499999999999) alih-alih
angka yang seharusnya saya dapatkan (misalnya, 19.95)?".
Sebagai contoh, ini
cetak int(0.6/0.2-2), "\n";
akan di sebagian besar komputer mencetak 0, bukan 1, karena bahkan angka sederhana seperti 0.6 dan 0.2
tidak dapat disajikan secara tepat dengan angka floating-point. Apa yang Anda pikirkan di atas sebagai
'tiga' benar-benar lebih seperti 2.9999999999999995559.
Mengapa tidak my oktal data ditafsirkan benar?
(disumbangkan oleh brian d foy)
Anda mungkin mencoba mengonversi string menjadi angka, yang hanya diubah Perl sebagai
angka desimal. Saat Perl mengonversi string menjadi angka, itu mengabaikan spasi di depan dan
nol, maka asumsikan sisa digit berada di basis 10:
$string saya = '0644';
cetak $string + 0; # mencetak 644
cetak $string + 44; # mencetak 688, tentu saja bukan oktal!
Masalah ini biasanya melibatkan salah satu bawaan Perl yang memiliki nama yang sama dengan Unix
perintah yang menggunakan bilangan oktal sebagai argumen pada baris perintah. Dalam contoh ini, "chmod"
pada baris perintah tahu bahwa argumen pertamanya adalah oktal karena itulah yang dilakukannya:
%prompt> file chmod 644
Jika Anda ingin menggunakan digit literal yang sama (644) di Perl, Anda harus memberi tahu Perl untuk memperlakukan
mereka sebagai angka oktal baik dengan awalan digit dengan 0 atau menggunakan "okt":
chmod( 0644, $namafile ); # benar, memiliki nol di depan
chmod( Oktober(644), $namafile ); #benar juga
Masalahnya muncul ketika Anda mengambil nomor Anda dari sesuatu yang menurut Perl adalah
string, seperti argumen baris perintah di @ARGV:
chmod( $ARGV[0], $namafile ); # salah, meskipun "0644"
chmod( okt($ARGV[0]), $namafile ); # benar, perlakukan string sebagai oktal
Anda selalu dapat memeriksa nilai yang Anda gunakan dengan mencetaknya dalam notasi oktal untuk memastikannya
sesuai dengan apa yang Anda pikir seharusnya. Cetak dalam format oktal dan desimal:
printf "0%o %d", $angka, $angka;
Apakah Perl memiliki a bulat() fungsi? Apa tentang langit-langit() dan lantai()? Trigonometri fungsi?
Ingat bahwa "int()" hanya dipotong menuju 0. Untuk pembulatan ke sejumlah
digit, "sprintf()" atau "printf()" biasanya merupakan rute termudah.
printf("%.3f", 3.1415926535); # cetakan 3.142
Modul POSIX (bagian dari distribusi Perl standar) mengimplementasikan "ceil()", "floor()",
dan sejumlah fungsi matematika dan trigonometri lainnya.
gunakan POSIX;
my $ceil = ceil(3.5); #4
$lantai saya = lantai(3.5); # 3
Dalam 5.000 hingga 5.003 perls, trigonometri dilakukan dalam modul Math::Complex. Dengan 5.004,
modul Math::Trig (bagian dari distribusi Perl standar) mengimplementasikan
fungsi trigonometri. Secara internal menggunakan modul Math::Complex dan beberapa fungsi
dapat keluar dari sumbu nyata ke bidang kompleks, misalnya sinus terbalik dari
2.
Pembulatan dalam aplikasi keuangan dapat memiliki implikasi serius, dan metode pembulatan
digunakan harus ditentukan dengan tepat. Dalam kasus ini, mungkin membayar untuk tidak percaya
sistem pembulatan mana pun yang digunakan oleh Perl, melainkan untuk menerapkan pembulatan
fungsi yang Anda butuhkan sendiri.
Untuk mengetahui alasannya, perhatikan bagaimana Anda masih memiliki masalah pada pergantian titik setengah jalan:
for ($i saya = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}
0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX
0.8 0.8 0.9 0.9 1.0 1.0
Jangan salahkan Perl. Sama seperti di C. IEEE mengatakan kita harus melakukan ini. Nomor Perl yang
nilai absolut adalah bilangan bulat di bawah 2**31 (pada mesin 32-bit) akan berfungsi seperti
bilangan bulat matematika. Nomor lain tidak dijamin.
Seterpercayaapakah Olymp Trade? Kesimpulan do I mengubah antara numerik representasi/basis/radix?
Seperti biasa dengan Perl ada lebih dari satu cara untuk melakukannya. Di bawah ini adalah beberapa contoh
pendekatan untuk membuat konversi umum antara representasi nomor. Ini dimaksudkan
untuk menjadi representasional daripada lengkap.
Beberapa contoh nanti di perlfaq4 menggunakan modul Bit::Vector dari CPAN. Alasannya
Anda dapat memilih Bit::Vector daripada fungsi bawaan Perl yang berfungsi dengan
jumlah ukuran APAPUN, yang dioptimalkan untuk kecepatan pada beberapa operasi, dan setidaknya
beberapa pemrogram notasinya mungkin sudah tidak asing lagi.
Bagaimana cara mengubah heksadesimal menjadi desimal?
Menggunakan konversi notasi "0x" bawaan Perl:
$dec saya = 0xDEADBEEF;
Menggunakan fungsi "hex":
my $dec = hex("DEADBEEF");
Menggunakan "paket":
my $dec = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8)));
Menggunakan modul CPAN "Bit::Vector":
gunakan Bit::Vektor;
my $vec = Bit::Vector->new_Hex(32, "DEADBEEF");
$dec saya = $vec->to_Dec();
Bagaimana cara mengubah dari desimal ke heksadesimal?
Menggunakan "sprintf":
$hex saya = sprintf("%X", 3735928559); # AF huruf besar
$hex saya = sprintf("%x", 3735928559); # huruf kecil af
Menggunakan "membongkar":
my $hex = unpack("H*", pack("N", 3735928559));
Menggunakan Bit::Vektor:
gunakan Bit::Vektor;
$vec saya = Bit::Vector->new_Dec(32, -559038737);
$hex saya = $vec->to_Hex();
Dan Bit::Vector mendukung jumlah bit ganjil:
gunakan Bit::Vektor;
$vec saya = Bit::Vector->new_Dec(33, 3735928559);
$vec->Resize(32); # tekan 0 di depan jika tidak diinginkan
$hex saya = $vec->to_Hex();
Bagaimana cara mengubah dari oktal ke desimal?
Menggunakan konversi angka bawaan Perl dengan nol di depan:
$dec saya = 033653337357; # perhatikan 0 di depan!
Menggunakan fungsi "okt":
my $dec = oct("33653337357");
Menggunakan Bit::Vektor:
gunakan Bit::Vektor;
$vec saya = Bit::Vector->yang baru(32);
$vec->Chunk_List_Store(3, split(//, membalikkan "33653337357"));
$dec saya = $vec->to_Dec();
Bagaimana cara mengubah dari desimal ke oktal?
Menggunakan "sprintf":
$okt saya = sprintf("%o", 3735928559);
Menggunakan Bit::Vektor:
gunakan Bit::Vektor;
$vec saya = Bit::Vector->new_Dec(32, -559038737);
my $oct = reverse join('', $vec->Potongan_Daftar_Baca(3));
Bagaimana cara mengubah dari biner ke desimal?
Perl 5.6 memungkinkan Anda menulis bilangan biner secara langsung dengan notasi "0b":
$nomor saya = 0b10110110;
Menggunakan "okt":
$masukan saya = "10110110";
my $desimal = oct( "0b$input" );
Menggunakan "paket" dan "ord":
my $desimal = ord(pack('B8', '10110110'));
Menggunakan "pack" dan "unpack" untuk string yang lebih besar:
my $int = unpack("N", pack("B32",
substr("0" x 32 . "11110101011011011111011101111", -32)));
$dec saya = sprintf("%d", $int);
# substr() digunakan untuk menempatkan string 32 karakter di sebelah kiri dengan nol.
Menggunakan Bit::Vektor:
my $vec = Bit::Vector->new_Bin(32, "11011110101011011011111011101111");
$dec saya = $vec->to_Dec();
Bagaimana cara mengubah dari desimal ke biner?
Menggunakan "sprintf" (Perl 5.6+):
$bin saya = sprintf("%b", 3735928559);
Menggunakan "membongkar":
my $bin = unpack("B*", pack("N", 3735928559));
Menggunakan Bit::Vektor:
gunakan Bit::Vektor;
$vec saya = Bit::Vector->new_Dec(32, -559038737);
$bin saya = $vec->to_Bin();
Transformasi yang tersisa (misalnya hex -> oct, bin -> hex, dll.) dibiarkan sebagai
latihan untuk pembaca yang cenderung.
Mengapa tidak & kerja itu cara I ingin it untuk?
Perilaku operator aritmatika biner tergantung pada apakah mereka digunakan pada angka atau
string. Operator memperlakukan string sebagai serangkaian bit dan bekerja dengan itu (string
"3" adalah pola bit 00110011). Operator bekerja dengan bentuk biner dari suatu bilangan (the
nomor 3 diperlakukan sebagai pola bit 00000011).
Jadi, mengatakan "11 & 3" melakukan operasi "dan" pada angka (menghasilkan 3). Mengatakan "11" &
"3" melakukan operasi "dan" pada string (menghasilkan "1").
Sebagian besar masalah dengan "&" dan "|" muncul karena programmer mengira mereka memiliki nomor tetapi
benar-benar itu string atau sebaliknya. Untuk menghindari ini, tegaskan argumen secara eksplisit
(menggunakan "" atau "qq()") atau mengonversinya menjadi angka secara eksplisit (menggunakan "0+$arg"). Sisanya
muncul karena programmer mengatakan:
if ("\020\020" & "\101\101") {
# ...
}
tetapi string yang terdiri dari dua byte nol (hasil dari "\020\020" & "\101\101") bukan
nilai palsu di Perl. Anda membutuhkan:
if ( ("\020\020" & "\101\101") !~ /[^\000]/) {
# ...
}
Seterpercayaapakah Olymp Trade? Kesimpulan do I mengalikan matriks?
Gunakan modul Math::Matrix atau Math::MatrixReal (tersedia dari CPAN) atau PDL
ekstensi (juga tersedia dari CPAN).
Seterpercayaapakah Olymp Trade? Kesimpulan do I melakukan an operasi on a seri of bilangan bulat?
Untuk memanggil fungsi pada setiap elemen dalam array, dan mengumpulkan hasilnya, gunakan:
@hasil saya = peta { my_func($_) } @array;
Sebagai contoh:
@triple saya = peta { 3 * $_ } @single;
Untuk memanggil fungsi pada setiap elemen array, tetapi mengabaikan hasilnya:
foreach $iterator saya (@array) {
some_func($iterator);
}
Untuk memanggil fungsi pada setiap bilangan bulat dalam rentang (kecil), Anda bisa menggunakan:
@hasil saya = peta { some_func($_) } (5 .. 25);
tetapi Anda harus menyadari bahwa dalam formulir ini, operator ".." membuat daftar semua
bilangan bulat dalam kisaran, yang dapat mengambil banyak memori untuk rentang besar. Namun,
masalah tidak terjadi saat menggunakan ".." dalam loop "untuk", karena dalam hal ini jangkauannya
operator dioptimalkan untuk pengulangan selama rentang, tanpa membuat seluruh daftar. Jadi
@hasil saya = ();
untuk $i saya (5 .. 500_005) {
push(@hasil, some_func($i));
}
atau bahkan
push(@results, some_func($_)) untuk 5 .. 500_005;
tidak akan membuat daftar antara 500,000 bilangan bulat.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I keluaran Roma angka?
Ambilhttp://www.cpan.org/modules/by-module/Roman> modul.
Mengapa tidak my acak nomor acak?
Jika Anda menggunakan versi Perl sebelum 5.004, Anda harus memanggil "srand" sekali di awal
program Anda untuk menyemai generator nomor acak.
MULAI { srand() jika $] < 5.004 }
5.004 dan yang lebih baru secara otomatis memanggil "srand" di awal. Jangan panggil "srand" lebih dari
sekali--Anda membuat nomor Anda kurang acak, bukan lebih.
Komputer bagus untuk diprediksi dan buruk dalam hal acak (terlepas dari penampilannya
disebabkan oleh bug di program Anda :-). Itu acak artikel di "Jauh Lebih Dari Yang Pernah Anda"
Koleksi Wanted To Know" dihttp://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz>, milik
Tom Phoenix, berbicara lebih banyak tentang ini. John von Neumann berkata, "Siapa pun yang mencoba untuk
menghasilkan angka acak dengan cara deterministik, tentu saja, hidup dalam keadaan berdosa."
Perl bergantung pada sistem yang mendasari penerapan "rand" dan "srand"; pada beberapa
sistem, angka yang dihasilkan tidak cukup acak (terutama pada Windows: lihat
<http://www.perlmonks.org/?node_id=803632>). Beberapa modul CPAN di namespace "Matematika"
mengimplementasikan generator pseudorandom yang lebih baik; lihat misalnya Math::Random::MT ("Mersenne
Twister", cepat), atau Math::TrulyRandom (menggunakan ketidaksempurnaan dalam pengatur waktu sistem untuk
menghasilkan angka acak, yang agak lambat). Lebih banyak algoritma untuk bilangan acak adalah
dijelaskan dalam "Resep Numerik dalam C" dihttp://www.nr.com/>
Seterpercayaapakah Olymp Trade? Kesimpulan do I mendapatkan a acak jumlah antara X dan Y?
Untuk mendapatkan nomor acak di antara dua nilai, Anda dapat menggunakan built-in "Rand()" untuk mendapatkan a
nomor acak antara 0 dan 1. Dari sana, Anda menggesernya ke kisaran yang Anda inginkan.
"rand($x)" mengembalikan angka sehingga "0 <= rand($x) < $x". Jadi apa yang ingin Anda miliki
perl figure out adalah angka acak dalam kisaran dari 0 hingga perbedaan antara Anda X
dan Y.
Artinya, untuk mendapatkan angka antara 10 dan 15, inklusif, Anda menginginkan angka acak antara 0
dan 5 yang kemudian dapat Anda tambahkan ke 10.
$angka saya = 10 + int rand( 15-10+1 ); # ( 10,11,12,13,14, atau 15 )
Karenanya Anda memperoleh fungsi sederhana berikut untuk mengabstraksikannya. Ini memilih secara acak
bilangan bulat antara dua bilangan bulat yang diberikan (inklusif). Sebagai contoh:
"random_int_between(50,120)".
sub random_int_antara {
saya($min, $maks) = @_;
# Asumsikan bahwa kedua argumen itu sendiri adalah bilangan bulat!
kembalikan $min jika $min == $max;
($min, $max) = ($max, $min) jika $min > $max;
kembalikan $min + int rand(1 + $max - $min);
}
Tanggal: Tanggal
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan itu hari or minggu of itu tahun?
Hari dalam setahun ada dalam daftar yang dikembalikan oleh fungsi "waktu lokal". Tanpa
argumen "localtime" menggunakan waktu saat ini.
my $day_of_year = (waktu setempat)[7];
Modul POSIX juga dapat memformat tanggal sebagai hari dalam setahun atau minggu dalam setahun.
gunakan POSIX qw/strftime/;
my $day_of_year = strftime "%j", waktu lokal;
my $week_of_year = strftime "%W", waktu lokal;
Untuk mendapatkan hari dalam setahun untuk tanggal apa pun, gunakan "mktime" POSIX untuk mendapatkan waktu dalam hitungan detik
untuk argumen ke "waktu lokal".
gunakan POSIX qw/mktime strftime/;
my $week_of_year = strftime "%W",
waktu lokal( mktime( 0, 0, 0, 18, 11, 87 ) );
Anda juga dapat menggunakan Time::Piece, yang disertakan dengan Perl dan menyediakan "waktu lokal" yang
mengembalikan objek:
gunakan Waktu::Sepotong;
my $day_of_year = localtime->yday;
$week_of_year = waktu lokal->minggu saya;
Modul Date::Calc juga menyediakan dua fungsi untuk menghitung ini:
gunakan Tanggal::Calc;
my $day_of_year = Day_of_year( 1987, 12, 18 );
$minggu_tahun_saya = Minggu_tahun_( 1987, 12, 18 );
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan itu arus abad or milenium?
Gunakan fungsi sederhana berikut:
sub get_abad {
return int((((waktu setempat(shift || waktu))[5] + 1999))/100);
}
sub get_milenium {
return 1+int((((waktu setempat(shift || waktu))[5] + 1899))/1000);
}
Pada beberapa sistem, fungsi "strftime()" modul POSIX telah diperluas dalam non-
cara standar untuk menggunakan format %C, yang terkadang mereka klaim sebagai "abad". Bukan,
karena pada kebanyakan sistem seperti itu, ini hanya dua digit pertama dari empat digit tahun,
dan dengan demikian tidak dapat digunakan untuk menentukan dengan andal abad atau milenium saat ini.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I membandingkan dua tanggal dan menemukan itu perbedaan?
(disumbangkan oleh brian d foy)
Anda bisa menyimpan semua tanggal Anda sebagai angka dan kemudian mengurangi. Hidup tidak selalu seperti itu
sederhana sekalipun.
Modul Time::Piece, yang disertakan dengan Perl, menggantikan waktu lokal dengan versi yang
mengembalikan sebuah objek. Itu juga membebani operator perbandingan sehingga Anda dapat membandingkannya
langsung:
gunakan Waktu::Sepotong;
$date1 saya = localtime( $some_time );
$date2 saya = waktu lokal( $some_other_time );
jika( $tanggal1 < $tanggal2 ) {
print "Tanggal sudah lewat\n";
}
Anda juga bisa mendapatkan perbedaan dengan pengurangan, yang mengembalikan objek Time::Seconds:
$diff saya = $date1 - $date2;
print "Perbedaannya adalah ", $date_diff->hari, " hari\n";
Jika Anda ingin bekerja dengan tanggal yang diformat, modul Date::Manip, Date::Calc, atau DateTime
bisa membantumu.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mengambil a string dan giliran it ke masa detik?
Jika itu adalah string yang cukup teratur sehingga selalu memiliki format yang sama, Anda dapat membaginya
dan berikan bagian ke "timelocal" dalam modul Time::Local standar. Jika tidak, Anda
harus melihat modul Date::Calc, Date::Parse, dan Date::Manip dari CPAN.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I menemukan itu Julian Hari?
(disumbangkan oleh brian d foy dan Dave Cross)
Anda dapat menggunakan modul Time::Piece, bagian dari Pustaka Standar, yang dapat mengonversi a
tanggal/waktu ke Hari Julian:
$ perl -MTime::Piece -le 'print localtime->julian_day'
2455607.7959375
Atau Hari Julian yang dimodifikasi:
$ perl -MTime::Piece -le 'print localtime->mjd'
55607.2961226851
Atau bahkan hari dalam setahun (yang oleh sebagian orang dianggap sebagai hari Julian):
$ perl -MTime::Piece -le 'print localtime->yday'
45
Anda juga dapat melakukan hal yang sama dengan modul DateTime:
$ perl -MDateTime -le'print DateTime->hari ini->jd'
2453401.5
$ perl -MDateTime -le'print DateTime->hari ini->mjd'
53401
$ perl -MDateTime -le'print DateTime->hari ini->doy'
31
Anda dapat menggunakan modul Time::JulianDay yang tersedia di CPAN. Pastikan Anda benar-benar ingin
temukan hari Julian, karena banyak orang memiliki ide berbeda tentang hari Julian (lihat
<http://www.hermetic.ch/cal_stud/jdn.htm> misalnya):
$ perl -MTime::JulianDay -le 'print local_julian_day( time )'
55608
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan kemarin tanggal?
(disumbangkan oleh brian d foy)
Untuk melakukannya dengan benar, Anda dapat menggunakan salah satu modul "Tanggal" karena berfungsi dengan kalender
bukannya kali. Modul DateTime membuatnya sederhana, dan memberi Anda waktu yang sama setiap hari,
hanya sehari sebelumnya, meskipun waktu musim panas berubah:
gunakan DateTime;
my $kemarin = DateTime->now->subtract( days => 1 );
print "Kemarin adalah $kemarin\n";
Anda juga dapat menggunakan modul Date::Calc menggunakan fungsi "Today_and_Now" -nya.
gunakan Date::Calc qw( Today_and_Now Add_Delta_DHMS );
@date_time saya = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
print "@tanggal_waktu\n";
Kebanyakan orang mencoba menggunakan waktu daripada kalender untuk menentukan tanggal, tapi itu
mengasumsikan bahwa hari adalah dua puluh empat jam masing-masing. Bagi kebanyakan orang, ada dua hari dalam setahun
ketika mereka tidak: beralih ke dan dari waktu musim panas membuang ini. Misalnya,
sisa saran terkadang salah:
Dimulai dengan Perl 5.10, Time::Piece dan Time::Seconds adalah bagian dari standar
distribusi, sehingga Anda mungkin berpikir bahwa Anda dapat melakukan sesuatu seperti ini:
gunakan Waktu::Sepotong;
gunakan Waktu :: Detik;
$kemarin saya = waktu lokal() - SATU_HARI; # SALAH
print "Kemarin adalah $kemarin\n";
Modul Time::Piece mengekspor "localtime" baru yang mengembalikan objek, dan Time::Seconds
mengekspor konstanta "ONE_DAY" yang merupakan jumlah detik yang ditentukan. Artinya selalu
memberikan waktu 24 jam yang lalu, yang tidak selalu kemarin. Ini dapat menyebabkan masalah di sekitar
akhir waktu musim panas ketika ada satu hari yang panjangnya 25 jam.
Anda memiliki masalah yang sama dengan Time::Local, yang akan memberikan jawaban yang salah untuk itu
kasus khusus yang sama:
# disumbangkan oleh Gunnar Hjalmarsson
gunakan Waktu::Lokal;
my $hari ini = waktu lokal 0, 0, 12, ( waktu lokal )[3..5];
my ($d, $m, $y) = ( waktu lokal $hari ini-86400 )[3..5]; # SALAH
printf "Kemarin: %d-%02d-%02d\n", $y+1900, $m+1, $d;
Apakah Perl memiliki a Tahun 2000 or 2038 masalah? Is Perl Y2K sesuai?
(disumbangkan oleh brian d foy)
Perl sendiri tidak pernah memiliki masalah Y2K, meskipun itu tidak pernah menghentikan orang untuk membuat Y2K
masalah mereka sendiri. Lihat dokumentasi untuk "waktu lokal" untuk penggunaan yang benar.
Dimulai dengan Perl 5.12, "localtime" dan "gmtime" dapat menangani tanggal setelah 03:14:08 Januari
19, 2038, ketika waktu berbasis 32-bit akan meluap. Anda mungkin masih mendapatkan peringatan di a
32-bit "perl":
% perl5.12 -E 'sebutkan waktu lokal skalar( 0x9FFF_FFFFFFFF )'
Integer overflow dalam bilangan heksadesimal pada -e baris 1.
Rabu 1 Nov 19:42:39 5576711
Pada "perl" 64-bit, Anda bisa mendapatkan tanggal yang lebih besar untuk proyek yang berjalan sangat lama:
% perl5.12 -E 'katakanlah skalar gmtime( 0x9FFF_FFFFFFFF )'
Kamis 2 Nov 00:42:39 5576711
Anda masih kurang beruntung jika Anda perlu melacak proton yang membusuk.
Tanggal: String
Seterpercayaapakah Olymp Trade? Kesimpulan do I mengesahkan memasukkan?
(disumbangkan oleh brian d foy)
Ada banyak cara untuk memastikan bahwa nilai adalah apa yang Anda harapkan atau ingin terima. di samping itu
contoh spesifik yang kami bahas di perlfaq, Anda juga dapat melihat modul dengan
"Tegaskan" dan "Validasi" dalam namanya, bersama dengan modul lain seperti Regexp::Common.
Beberapa modul memiliki validasi untuk jenis input tertentu, seperti Business::ISBN,
Bisnis::Kartu Kredit, Email::Valid, dan Data::Validasi::IP.
Seterpercayaapakah Olymp Trade? Kesimpulan do I melepaskan diri a rangkaian?
Itu tergantung apa yang Anda maksud dengan "melarikan diri". Pelarian URL ditangani di perlfaq9. Kerang
lolos dengan karakter garis miring terbalik ("\") dihapus dengan
s/\\(.)/$1/g;
Ini tidak akan memperluas "\n" atau "\t" atau escape khusus lainnya.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menghapus berturut-turut pasang of karakter?
(disumbangkan oleh brian d foy)
Anda dapat menggunakan operator substitusi untuk menemukan pasangan karakter (atau rangkaian karakter)
dan menggantinya dengan satu contoh. Dalam substitusi ini, kami menemukan karakter di
"(.)". Tanda kurung memori menyimpan karakter yang cocok di referensi belakang "\g1" dan
kami menggunakannya untuk meminta hal yang sama segera mengikutinya. Kami mengganti bagian itu dari
string dengan karakter di $1.
s/(.)\g1/$1/g;
Kita juga dapat menggunakan operator transliterasi, "tr///". Dalam contoh ini, daftar pencarian
sisi "tr///" kami tidak berisi apa-apa, tetapi opsi "c" melengkapinya sehingga mengandung
semuanya. Daftar pengganti juga tidak berisi apa-apa, jadi transliterasinya hampir
no-op karena tidak akan melakukan penggantian (atau lebih tepatnya, ganti karakter dengan
diri). Namun, opsi "s" menekan karakter yang digandakan dan berurutan di
string sehingga karakter tidak muncul di sebelahnya
$str saya = 'Haarlem'; # di Belanda
$str =~ tr///cs; # Sekarang Harlem, seperti di New York
Seterpercayaapakah Olymp Trade? Kesimpulan do I memperluas fungsi panggilan in a rangkaian?
(disumbangkan oleh brian d foy)
Ini didokumentasikan dalam perlref, dan meskipun itu bukan hal yang paling mudah untuk dibaca, itu benar
kerja. Dalam setiap contoh ini, kami memanggil fungsi di dalam kurung kurawal yang digunakan untuk
dereferensi referensi. Jika kita memiliki lebih dari satu nilai balik, kita dapat membangun dan
dereference array anonim. Dalam hal ini, kami memanggil fungsi dalam konteks daftar.
print "Nilai waktunya adalah @{ [waktu setempat] }.\n";
Jika kita ingin memanggil fungsi dalam konteks skalar, kita harus melakukan lebih banyak pekerjaan. Kita dapat
benar-benar memiliki kode yang kita suka di dalam kurung, jadi kita hanya harus mengakhiri dengan skalar
referensi, meskipun bagaimana Anda melakukannya terserah Anda, dan Anda dapat menggunakan kode di dalam kurung kurawal.
Perhatikan bahwa penggunaan parens membuat konteks daftar, jadi kita memerlukan "skalar" untuk memaksa
konteks skalar pada fungsi:
print "Waktunya ${\(scalar localtime)}.\n"
print "Waktunya ${ my $x = localtime; \$x }.\n";
Jika fungsi Anda sudah mengembalikan referensi, Anda tidak perlu membuat referensi
dirimu sendiri.
sub timestamp { $t saya = waktu lokal; \$t }
print "Waktunya adalah ${ timestamp() }.\n";
Modul "Interpolasi" juga dapat melakukan banyak keajaiban untuk Anda. Anda dapat menentukan variabel
name, dalam hal ini "E", untuk menyiapkan hash terikat yang melakukan interpolasi untuk Anda. Memiliki
beberapa metode lain untuk melakukan ini juga.
gunakan Interpolasi E => 'eval';
print "Nilai waktunya adalah $E{localtime()}.\n";
Dalam kebanyakan kasus, mungkin lebih mudah menggunakan rangkaian string, yang juga memaksa
konteks skalar.
print "Waktunya". waktu lokal() . ".\n";
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan pencocokan/bersarang apa pun?
Untuk menemukan sesuatu di antara dua karakter tunggal, pola seperti "/x([^x]*)x/" akan mendapatkan
intervensi bit dalam $1. Untuk lebih dari satu, maka sesuatu yang lebih seperti "/alpha(.*?)omega/"
akan dibutuhkan. Untuk pola bersarang dan/atau ekspresi seimbang, lihat yang disebut
(?PARNO) konstruksi (tersedia sejak Perl 5.10). Modul CPAN Regexp::Common dapat membantu
untuk membangun ekspresi reguler seperti itu (lihat khususnya Regexp::Common::balanced dan
Regexp::Umum::dibatasi).
Kasus yang lebih kompleks akan membutuhkan untuk menulis parser, mungkin menggunakan modul parsing dari
CPAN, seperti Regexp::Grammars, Parse::RecDescent, Parse::Yapp, Text::Balanced, atau Marpa::R2.
Seterpercayaapakah Olymp Trade? Kesimpulan do I membalikkan a rangkaian?
Gunakan "reverse()" dalam konteks skalar, seperti yang didokumentasikan dalam "reverse" di perlfunc.
my $terbalik = membalikkan $string;
Seterpercayaapakah Olymp Trade? Kesimpulan do I memperluas tab in a rangkaian?
Anda dapat melakukannya sendiri:
1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
Atau Anda bisa menggunakan modul Text::Tabs (bagian dari distribusi Perl standar).
gunakan Teks::Tab;
@expanded_lines saya = expand(@lines_with_tabs);
Seterpercayaapakah Olymp Trade? Kesimpulan do I memformat ulang a gugus kalimat?
Gunakan Text::Wrap (bagian dari distribusi Perl standar):
gunakan Teks::Bungkus;
print wrap("\t", ' ', @paragraf);
Paragraf yang Anda berikan ke Text::Wrap tidak boleh berisi baris baru yang disematkan. Teks::Bungkus
tidak membenarkan garis (flush-right).
Atau gunakan modul CPAN Text::Autoformat. Memformat file dapat dengan mudah dilakukan dengan membuat
shell alias, seperti:
alias fmt="perl -i -MText::Autoformat -n0777 \
-e 'cetak format otomatis $_, {all=>1}' $*"
Lihat dokumentasi untuk Text::Autoformat untuk menghargai banyak kemampuannya.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mengakses or perubahan N karakter of a rangkaian?
Anda dapat mengakses karakter pertama dari string dengan substr(). Untuk mendapatkan yang pertama
karakter, misalnya, mulai dari posisi 0 dan ambil string dengan panjang 1.
my $string = "Hanya Perl Hacker lain";
my $first_char = substr( $string, 0, 1 ); # 'J'
Untuk mengubah bagian dari string, Anda dapat menggunakan argumen keempat opsional yang merupakan
tali pengganti.
substr( $string, 13, 4, "Perl 5.8.0" );
Anda juga dapat menggunakan substr() sebagai nilai.
substr( $string, 13, 4 ) = "Perl 5.8.0";
Seterpercayaapakah Olymp Trade? Kesimpulan do I perubahan itu Tidak kejadian of sesuatu?
Anda harus melacak N sendiri. Misalnya, Anda ingin mengubah yang kelima
terjadinya "siapa pun" atau "siapa pun" menjadi "siapa pun" atau "siapa pun", kasus
tidak peka. Ini semua mengasumsikan bahwa $_ berisi string yang akan diubah.
$ Hitung = 0;
s{((siapa?)pernah)}{
++$hitung == 5 # apakah ini yang ke-5?
? "${2}soever" # ya, tukar
: $1 # mengingkari dan meninggalkannya di sana
}saya;
Dalam kasus yang lebih umum, Anda dapat menggunakan pengubah "/ g" dalam loop "sementara", dengan tetap menghitung
pertandingan.
$INGIN = 3;
$ Hitung = 0;
$_ = "Satu ikan dua ikan merah ikan biru ikan";
while (/(\w+)\s+ikan\b/gi) {
if (++$hitung == $INGIN) {
print "Ikan ketiga adalah $1.\n";
}
}
Itu mencetak: "Ikan ketiga adalah yang merah." Anda juga dapat menggunakan hitungan pengulangan dan
pola berulang seperti ini:
/(?:\w+\s+ikan\s+){2}(\w+)\s+ikan/i;
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I menghitung itu jumlah of kejadian of a BERGANTI dalam a rangkaian?
Ada beberapa cara, dengan efisiensi yang berbeda-beda. Jika Anda ingin hitungan tertentu
karakter tunggal (X) di dalam string, Anda dapat menggunakan fungsi "tr///" seperti:
my $string = "ThisXlineXhasXsomeXx'sXinXit";
$count = ($string =~ tr/X//);
print "Ada $count X karakter dalam string";
Ini bagus jika Anda hanya mencari satu karakter. Namun, jika Anda mencoba untuk
menghitung beberapa substring karakter dalam string yang lebih besar, "tr///" tidak akan berfungsi. Apa yang kamu?
bisa lakukan adalah membungkus ketika() loop di sekitar kecocokan pola global. Misalnya, mari kita berhitung
bilangan bulat negatif:
my $string = "-9 55 48 -2 23 -76 4 14 -44";
$hitungan saya = 0;
while ($string =~ /-\d+/g) { $hitung++ }
print "Ada $count bilangan negatif dalam string";
Versi lain menggunakan kecocokan global dalam konteks daftar, lalu menetapkan hasilnya ke skalar,
menghasilkan hitungan jumlah pertandingan.
$hitungan saya = () = $string =~ /-\d+/g;
Seterpercayaapakah Olymp Trade? Kesimpulan do I bermodalkan semua itu kata on satu garis?
(disumbangkan oleh brian d foy)
Teks Damian Conway::Autoformat menangani semua pemikiran untuk Anda.
gunakan Teks::Format otomatis;
my $x = "Dr. Strangelove atau: Bagaimana Saya Belajar Berhenti".
"Khawatir dan Cinta Bom";
cetak $x, "\n";
untuk $style saya (qw( sorotan judul kalimat )) {
print autoformat($x, { case => $style }), "\n";
}
Bagaimana Anda ingin menggunakan huruf besar untuk kata-kata itu?
FRED AND BARNEY'S LODGE # semua huruf besar
Fred And Barney's Lodge # judul kasus
Fred and Barney's Lodge # kasus utama
Ini tidak semudah masalah seperti yang terlihat. Menurut Anda berapa banyak kata yang ada di sana? Tunggu
itu ... tunggu .... Jika Anda menjawab 5 Anda benar. Kata Perl adalah grup dari "\w+", tapi
bukan itu yang ingin Anda kapitalkan. Bagaimana Perl seharusnya tahu untuk tidak menggunakan huruf besar
bahwa "s" setelah apostrof? Anda dapat mencoba ekspresi reguler:
$string =~ s/(
(^\w) #di awal baris
| # atau
(\s\w) #diawali dengan spasi
)
/\U$1/xg;
$string =~ s/([\w']+)/\u\L$1/g;
Sekarang, bagaimana jika Anda tidak ingin menggunakan huruf besar "dan" itu? Cukup gunakan Teks::Format otomatis dan mulai
dengan masalah berikutnya. :)
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I membagi a [karakter]-dibatasi string kecuali ketika dalam [karakter]?
Beberapa modul dapat menangani penguraian semacam ini--Teks::Seimbang, Teks::CSV, Teks::CSV_XS,
dan Teks::ParseWords, antara lain.
Ambil contoh kasus mencoba untuk membagi string yang dipisahkan koma menjadi nya
bidang yang berbeda. Anda tidak dapat menggunakan "split(/,/)" karena Anda tidak boleh membagi jika koma
kutipan dalam. Misalnya, ambil baris data seperti ini:
SAR001,"","Cimetrix, Inc",,"Bob Smith",,"CAM",N,8,1,0,7,"Kesalahan, Core Dibuang"
Karena pembatasan tanda kutip, ini adalah masalah yang cukup kompleks. Syukurlah, kami
memiliki Jeffrey Friedl, penulis Menguasai Reguler Ekspresi, untuk menangani ini untuk kita. Dia
menyarankan (dengan asumsi string Anda terkandung dalam $text):
saya @baru = ();
push(@new, $+) sementara $teks =~ m{
"([^\"\\]*(?:\\.[^\"\\]*)*)",? # kelompokkan frasa di dalam tanda kutip
| ([^,]+),?
| ,
}gx;
push(@new, undef) if substr($text,-1,1) eq ',';
Jika Anda ingin merepresentasikan tanda kutip di dalam bidang yang dibatasi tanda kutip, escape
mereka dengan garis miring terbalik (misalnya, "seperti \"ini\"".
Atau, modul Text::ParseWords (bagian dari distribusi Perl standar) memungkinkan
kamu bilang:
gunakan Teks::ParseWords;
@new = kutipankata(",", 0, $teks);
Namun, untuk menguraikan atau menghasilkan CSV, gunakan Text::CSV daripada mengimplementasikannya
diri Anda sangat dianjurkan; Anda akan menyelamatkan diri Anda dari bug aneh yang muncul nanti hanya dengan
menggunakan kode yang telah dicoba dan diuji dalam produksi selama bertahun-tahun.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menelanjangi kosong ruang dari itu awal/akhir of a rangkaian?
(disumbangkan oleh brian d foy)
Substitusi dapat melakukan ini untuk Anda. Untuk satu baris, Anda ingin mengganti semua yang terkemuka
atau membuntuti spasi putih tanpa apa-apa. Anda dapat melakukannya dengan sepasang substitusi:
s/^\s+//;
s/\s+$//;
Anda juga dapat menulisnya sebagai substitusi tunggal, meskipun ternyata gabungan
pernyataan lebih lambat dari yang terpisah. Itu mungkin tidak masalah bagi Anda, meskipun:
s/^\s+|\s+$//g;
Dalam ekspresi reguler ini, pergantian cocok di awal atau di akhir
string karena jangkar memiliki prioritas lebih rendah daripada pergantian. Dengan "/g"
flag, substitusi membuat semua kemungkinan kecocokan, sehingga mendapat keduanya. Ingat, jejaknya
baris baru cocok dengan "\s+", dan jangkar "$" dapat cocok dengan akhir absolut dari
string, jadi baris baru juga menghilang. Cukup tambahkan baris baru ke output, yang memiliki
manfaat tambahan dari mempertahankan baris "kosong" (seluruhnya terdiri dari spasi putih) yang
"^\s+" akan menghapus dengan sendirinya:
sementara( <> ) {
s/^\s+|\s+$//g;
cetak "$_\n";
}
Untuk string multi-baris, Anda dapat menerapkan ekspresi reguler ke setiap baris logis di
string dengan menambahkan tanda "/m" (untuk "multi-baris"). Dengan bendera "/ m", "$" cocok
sebelum baris baru yang disematkan, sehingga tidak menghapusnya. Pola ini masih menghilangkan
baris baru di akhir string:
$string =~ s/^\s+|\s+$//gm;
Ingat bahwa garis yang seluruhnya terdiri dari spasi akan hilang, sejak bagian pertama
dari pergantian dapat mencocokkan seluruh string dan menggantinya dengan apa pun. Jika Anda perlu
tetap menyematkan baris kosong, Anda harus melakukan sedikit lebih banyak pekerjaan. Alih-alih mencocokkan apa pun
spasi putih (karena itu termasuk baris baru), cocokkan dengan spasi putih lainnya:
$string =~ s/^[\t\f ]+|[\t\f ]+$//mg;
Seterpercayaapakah Olymp Trade? Kesimpulan do I bantalan a string dengan kosong or bantalan a jumlah dengan nol?
Dalam contoh berikut, $pad_len adalah panjang string yang ingin Anda padukan,
$text atau $num berisi string yang akan diisi, dan $pad_char berisi padding
karakter. Anda dapat menggunakan konstanta string karakter tunggal alih-alih $pad_char
variabel jika Anda tahu apa itu sebelumnya. Dan dengan cara yang sama Anda dapat menggunakan bilangan bulat di
tempat $pad_len jika Anda mengetahui panjang pad sebelumnya.
Metode paling sederhana menggunakan fungsi "sprintf". Itu bisa pad di kiri atau kanan dengan
kosong dan di sebelah kiri dengan nol dan tidak akan memotong hasilnya. "Paket"
fungsi hanya dapat mengisi string di sebelah kanan dengan yang kosong dan itu akan memotong hasilnya menjadi
panjang maksimum $pad_len.
# Kiri mengisi string dengan kosong (tanpa pemotongan):
$empuk saya = sprintf("%${pad_len}s", $teks);
my $padded = sprintf("%*s", $pad_len, $teks); # hal yang sama
# Padding kanan string dengan kosong (tanpa pemotongan):
my $padded = sprintf("%-${pad_len}s", $text);
my $padded = sprintf("%-*s", $pad_len, $teks); # hal yang sama
# Mengisi nomor dengan 0 (tanpa pemotongan):
my $padded = sprintf("%0${pad_len}d", $num);
my $padded = sprintf("%0*d", $pad_len, $num); # hal yang sama
# Mengisi kanan string dengan kosong menggunakan paket (akan terpotong):
my $padded = pack("A$pad_len",$teks);
Jika Anda perlu mengisi dengan karakter selain kosong atau nol, Anda dapat menggunakan salah satu dari
metode berikut. Mereka semua menghasilkan string pad dengan operator "x" dan menggabungkannya
dengan $teks. Metode ini tidak memotong $text.
Padding kiri dan kanan dengan karakter apa pun, membuat string baru:
my $padded = $pad_char x ( $pad_len - length( $text ) ) . $teks;
$empuk saya = $teks saya. $pad_char x ( $pad_len - panjang( $teks ) );
Padding kiri dan kanan dengan karakter apa pun, memodifikasi $text secara langsung:
substr( $teks, 0, 0 ) = $pad_char x ( $pad_len - panjang( $teks ) );
$teks .= $pad_char x ( $pad_len - panjang( $teks ) );
Seterpercayaapakah Olymp Trade? Kesimpulan do I ekstrak terpilih kolom dari a rangkaian?
(disumbangkan oleh brian d foy)
Jika Anda mengetahui kolom yang berisi data, Anda dapat menggunakan "substr" untuk mengekstrak satu
kolom.
$kolom saya = substr( $baris, $kolom_mulai, $panjang );
Anda dapat menggunakan "split" jika kolom dipisahkan oleh spasi atau pembatas lainnya, seperti
selama spasi putih atau pembatas tidak dapat muncul sebagai bagian dari data.
$line saya = ' fred barney betty ';
@columns saya = split /\s+/, $line;
# ( '', 'fred', 'barney', 'betty' );
my $line = 'fred||barney||betty';
@columns saya = split /\|/, $line;
# ( 'fred', '', 'barney', '', 'betty' );
Jika Anda ingin bekerja dengan nilai yang dipisahkan koma, jangan lakukan ini karena formatnya sedikit
lebih rumit. Gunakan salah satu modul yang menangani format tersebut, seperti Teks::CSV,
Teks::CSV_XS, atau Teks::CSV_PP.
Jika Anda ingin memecah seluruh baris kolom tetap, Anda dapat menggunakan "membongkar" dengan
format A (ASCII). Dengan menggunakan angka setelah penentu format, Anda dapat menunjukkan kolom
lebar. Lihat entri "pack" dan "unpack" di perlfunc untuk lebih jelasnya.
my @fields = unpack( $line, "A8 A8 A8 A16 A4" );
Perhatikan bahwa spasi dalam argumen format untuk "membongkar" tidak menunjukkan spasi literal. Jika kamu
memiliki data yang dipisahkan ruang, Anda mungkin ingin "membagi" sebagai gantinya.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan itu soundex nilai of a rangkaian?
(disumbangkan oleh brian d foy)
Anda dapat menggunakan modul "Teks::Soundex". Jika Anda ingin melakukan pencocokan fuzzy atau dekat, Anda
mungkin juga mencoba modul String::Approx, dan Text::Metaphone, dan Text::DoubleMetaphone.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I memperluas variabel in teks string?
(disumbangkan oleh brian d foy)
Jika Anda dapat menghindarinya, jangan, atau jika Anda dapat menggunakan sistem templating, seperti Teks::Templat
atau Template Toolkit, lakukan itu. Anda bahkan mungkin bisa menyelesaikan pekerjaan dengan
"sprintf" atau "printf":
my $string = sprintf 'Sapa %s dan %s', $foo, $bar;
Namun, untuk kasus sederhana satu kali di mana saya tidak ingin mengeluarkan templating lengkap
sistem, saya akan menggunakan string yang memiliki dua variabel skalar Perl di dalamnya. Dalam contoh ini, saya
ingin memperluas $foo dan $bar ke nilai variabelnya:
my $foo = 'Fred';
$bar saya = 'Barney';
$string = 'Sapa $foo dan $bar';
Salah satu cara saya bisa melakukan ini melibatkan operator substitusi dan bendera "/ e" ganda. Pertama
"/e" mengevaluasi $1 di sisi pengganti dan mengubahnya menjadi $foo. /e kedua dimulai
dengan $foo dan menggantinya dengan nilainya. $foo, kemudian, berubah menjadi 'Fred', dan itu
akhirnya apa yang tersisa di string:
$string =~ s/(\$\w+)/$1/eeg; # 'Sapa Fred dan Barney'
"/ e" juga akan diam-diam mengabaikan pelanggaran ketat, menggantikan variabel yang tidak ditentukan
nama dengan string kosong. Karena saya menggunakan flag "/e" (bahkan dua kali!), saya memiliki semuanya
masalah keamanan yang sama yang saya miliki dengan "eval" dalam bentuk string. Jika ada yang aneh
di $foo, mungkin sesuatu seperti "@{[ system "rm -rf /" ]}", maka saya bisa masuk
Masalah.
Untuk mengatasi masalah keamanan, saya juga bisa menarik nilai dari hash alih-alih
mengevaluasi nama variabel. Menggunakan satu "/ e", saya dapat memeriksa hash untuk memastikan nilainya
ada, dan jika tidak, saya dapat mengganti nilai yang hilang dengan penanda, dalam hal ini
"???" untuk menandakan bahwa saya melewatkan sesuatu:
my $string = 'Ini memiliki $foo dan $bar';
%Penggantian saya = (
foo => 'Fred',
);
# $string =~ s/\$(\w+)/$Penggantian{$1}/g;
$string =~ s/\$(\w+)/
ada $Replacements{$1} ? $Penggantian{$1} : '???'
/misalnya;
cetak $string;
Apa salah dengan selalu mengutip "$var"?
Masalahnya adalah bahwa tanda kutip ganda itu memaksa stringifikasi--memaksa angka dan
referensi ke string--bahkan ketika Anda tidak ingin mereka menjadi string. Pikirkan ini
cara: ekspansi tanda kutip ganda digunakan untuk menghasilkan string baru. Jika Anda sudah memiliki string,
mengapa Anda membutuhkan lebih banyak?
Jika Anda terbiasa menulis hal-hal aneh seperti ini:
cetak "$var"; # BURUK
$baru saya = "$lama"; # BURUK
somefunc("$var"); # BURUK
Anda akan berada dalam masalah. Itu harus (dalam 99.8% kasus) menjadi yang lebih sederhana dan lebih langsung:
cetak $var;
$baru saya = $lama;
somefunc($var);
Jika tidak, selain memperlambat Anda, Anda akan memecahkan kode saat benda di
skalar sebenarnya bukan string atau angka, tetapi referensi:
fungsi(\@array);
subfungsi {
$aref saya = shift;
my $oref = "$aref"; # SALAH
}
Anda juga bisa mendapatkan masalah halus pada beberapa operasi di Perl yang benar-benar melakukannya
peduli tentang perbedaan antara string dan angka, seperti "++" ajaib
operator kenaikan otomatis atau panggilan sistem() fungsi.
Stringifikasi juga menghancurkan array.
@baris saya = `perintah`;
cetak "@baris"; # SALAH - kosong ekstra
cetak @baris; # Baik
Mengapa tidak my < dokumen bekerja?
Di sini dokumen ditemukan di perlop. Periksa tiga hal ini:
Tidak boleh ada spasi setelah bagian <<.
Di sana (mungkin) harus ada titik koma di akhir token pembuka
Anda tidak dapat (dengan mudah) memiliki ruang di depan tag.
Harus ada setidaknya pemisah garis setelah token akhir.
Jika Anda ingin membuat indentasi teks dalam dokumen di sini, Anda dapat melakukan ini:
# semua dalam satu
($VAR saya = <
teks Anda
pergi ke sini
DI SINI_TARGET
Tapi HERE_TARGET harus tetap sejajar dengan margin. Jika Anda ingin itu menjorok
juga, Anda harus mengutip di lekukan.
($quote saya = <<' FINIS') =~ s/^\s+//gm;
...kita akan memiliki kedamaian, ketika Anda dan semua pekerjaan Anda memilikinya
binasa--dan pekerjaan tuan gelapmu yang kamu
akan membebaskan kita. Kamu pembohong, Saruman, dan koruptor
dari hati pria. --Theoden di /usr/src/perl/taint.c
AKHIR
$quote =~ s/\s+--/\n--/;
Fungsi fixer-upper serba guna yang bagus untuk indentasi di sini dokumen berikut. Dia
mengharapkan untuk dipanggil dengan dokumen di sini sebagai argumennya. Tampaknya untuk melihat apakah masing-masing
baris dimulai dengan substring umum, dan jika demikian, hapus substring itu. Jika tidak, itu
mengambil jumlah spasi putih terkemuka yang ditemukan di baris pertama dan menghapus sebanyak itu
setiap baris berikutnya.
sub-perbaikan {
lokal $_ = shift;
saya ($putih, $pemimpin); # spasi putih umum dan string utama umum
jika (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\g1\g2?.*\n)+$/) {
($putih, $pemimpin) = ($2, quotemeta($1));
} Else {
($putih, $pemimpin) = (/^(\s+)/, '');
}
s/^\s*?$pemimpin(?:$putih)?//gm;
kembali $_;
}
Ini berfungsi dengan string khusus terkemuka, ditentukan secara dinamis:
my $remember_the_main = fix<<' MAIN_INTERPRETER_LOOP';
@@@ masuk
@@@ runop() {
@@@ SIMPAN32(runlevel);
@@@ runlevel++;
@@@ while ( op = (*op->op_ppaddr)() );
@@@ TAINT_NOT;
@@@ kembali 0;
@@@ }
MAIN_INTERPRETER_LOOP
Atau dengan jumlah spasi awal yang tetap, dengan lekukan yang tersisa dengan benar
diawetkan:
$puisi saya = perbaiki<
Sekarang jauh di depan Jalan telah pergi,
Dan saya harus mengikuti, jika saya bisa,
Mengejarnya dengan kaki bersemangat,
Sampai bergabung dengan cara yang lebih besar
Dimana banyak jalan dan tugas bertemu.
Lalu kemana? Saya tidak dapat mengatakan.
--Bilbo di /usr/src/perl/pp_ctl.c
PERNAH_ON_AND_ON
Tanggal: Array
Apa is itu perbedaan antara a daftar dan an Himpunan?
(disumbangkan oleh brian d foy)
Daftar adalah kumpulan skalar yang tetap. Array adalah variabel yang menyimpan variabel
kumpulan skalar. Sebuah array dapat menyediakan koleksinya untuk operasi daftar, jadi daftar
operasi juga bekerja pada array:
# irisan
( 'anjing', 'kucing', 'burung' )[2,3];
@hewan[2,3];
# pengulangan
foreach ( qw( anjing kucing burung ) ) { ... }
foreach (@animals ) { ... }
my @three = grep { panjang == 3 } qw( anjing kucing burung );
saya @tiga = grep { panjang == 3 } @hewan;
# berikan daftar argumen
wash_animals( qw( anjing kucing burung ) );
cuci_hewan( @hewan );
Operasi array, yang mengubah skalar, mengatur ulang, atau menambah atau mengurangi beberapa
skalar, hanya bekerja pada array. Ini tidak dapat bekerja pada daftar, yang diperbaiki. Operasi larik
termasuk "shift", "unshift", "push", "pop", dan "sambatan".
Array juga dapat mengubah panjangnya:
$#hewan = 1; # terpotong menjadi dua elemen
$#hewan = 10000; # pra-perpanjang ke 10,001 elemen
Anda dapat mengubah elemen array, tetapi Anda tidak dapat mengubah elemen daftar:
$animals[0] = 'Rottweiler';
qw( anjing kucing burung )[0] = 'Rottweiler'; # kesalahan sintaks!
foreach (@animals ) {
s/^d/fr/; # bekerja dengan baik
}
foreach ( qw( anjing kucing burung ) ) {
s/^d/fr/; # Kesalahan! Modifikasi nilai hanya baca!
}
Namun, jika elemen daftar itu sendiri adalah variabel, tampaknya Anda dapat mengubah daftar
elemen. Namun, elemen daftar adalah variabel, bukan data. Anda tidak mengubah
elemen daftar, tetapi sesuatu yang dirujuk oleh elemen daftar. Elemen daftar itu sendiri tidak
perubahan: itu masih variabel yang sama.
Anda juga harus berhati-hati tentang konteks. Anda dapat menetapkan array ke skalar untuk mendapatkan
jumlah elemen dalam array. Ini hanya berfungsi untuk array, meskipun:
$hitungan saya = @hewan; # hanya berfungsi dengan array
Jika Anda mencoba melakukan hal yang sama dengan apa yang Anda pikir adalah daftar, Anda akan mendapatkan hasil yang sangat berbeda
hasil. Meskipun sepertinya Anda memiliki daftar di sisi kanan, Perl sebenarnya melihat
sekelompok skalar dipisahkan dengan koma:
my $scalar = ( 'anjing', 'kucing', 'burung' ); # $scalar mendapat burung
Karena Anda menetapkan skalar, sisi kanan berada dalam konteks skalar. koma
operator (ya, ini adalah operator!) dalam konteks skalar mengevaluasi sisi kirinya, melempar
membuang hasilnya, dan mengevaluasi sisi kanannya dan mengembalikan hasilnya. Akibatnya, itu
list-lookalike menetapkan $scalar itu nilai paling kanan. Banyak orang mengacaukan ini karena
mereka memilih daftar yang mirip yang elemen terakhirnya juga merupakan jumlah yang mereka harapkan:
$skalar saya = ( 1, 2, 3 ); # $scalar mendapat 3, secara tidak sengaja
Apa is itu perbedaan antara $array[1] dan @array[1]?
(disumbangkan oleh brian d foy)
Perbedaannya adalah sigil, karakter khusus di depan nama array. "$"
sigil berarti "tepat satu item", sedangkan "@" sigil berarti "nol atau lebih item". "$"
memberi Anda satu skalar, sedangkan "@" memberi Anda daftar.
Kebingungan muncul karena orang salah berasumsi bahwa sigil menunjukkan variabel
mengetik.
$array[1] adalah akses elemen tunggal ke array. Itu akan mengembalikan barangnya ke dalam
indeks 1 (atau undef jika tidak ada item di sana). Jika Anda berniat untuk mendapatkan tepat satu elemen
dari array, ini adalah formulir yang harus Anda gunakan.
@array[1] adalah irisan array, meskipun hanya memiliki satu indeks. Anda dapat menarik keluar
beberapa elemen secara bersamaan dengan menentukan indeks tambahan sebagai daftar, seperti
@array[1,4,3,0].
Menggunakan irisan di sisi kiri konteks daftar persediaan tugas ke
sisi kanan. Ini dapat menyebabkan hasil yang tidak terduga. Misalnya, jika Anda ingin membaca
satu baris dari filehandle, menetapkan ke nilai skalar baik-baik saja:
$array[1] = ;
Namun, dalam konteks daftar, operator input baris mengembalikan semua baris sebagai daftar. Itu
baris pertama masuk ke @array[1] dan baris lainnya menghilang secara misterius:
@array[1] = ; # kemungkinan besar bukan yang Anda inginkan
Entah pragma "gunakan peringatan" atau -w flag akan memperingatkan Anda ketika Anda menggunakan irisan array
dengan indeks tunggal.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I menghapus duplikat elemen dari a daftar or Himpunan?
(disumbangkan oleh brian d foy)
Gunakan hash. Ketika Anda memikirkan kata-kata "unik" atau "duplikat", pikirkan "kunci hash".
Jika Anda tidak peduli dengan urutan elemen, Anda bisa membuat hashnya
ekstrak kuncinya. Tidak penting bagaimana Anda membuat hash itu: hanya saja Anda menggunakan "kunci" untuk
mendapatkan elemen unik.
%hash saya = peta { $_, 1 } @array;
# atau irisan hash: @hash{ @array } = ();
# atau foreach: $hash{$_} = 1 foreach ( @array );
saya @unik = kunci %hash;
Jika Anda ingin menggunakan modul, coba fungsi "uniq" dari List::MoreUtils. Dalam konteks daftar
ia mengembalikan elemen unik, mempertahankan urutannya dalam daftar. Dalam konteks skalar, itu
mengembalikan jumlah elemen unik.
gunakan Daftar::MoreUtils qw(uniq);
saya @unik = unik( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 1,2,3,4,5,6,7
my $unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); #7
Anda juga dapat menelusuri setiap elemen dan melewati elemen yang pernah Anda lihat sebelumnya. Gunakan hash untuk
melacak. Pertama kali loop melihat sebuah elemen, elemen tersebut tidak memiliki kunci di %Seen. Itu
pernyataan "berikutnya" membuat kunci dan segera menggunakan nilainya, yaitu "undef", jadi
loop melanjutkan ke "push" dan menambah nilai untuk kunci itu. Lain kali loop
melihat elemen yang sama, kuncinya ada di hash dan nilai untuk kunci itu benar
(karena itu bukan 0 atau "undef"), jadi yang berikutnya melewatkan iterasi itu dan loop menuju ke
elemen berikutnya.
saya @unik = ();
%terlihat saya = ();
foreach $elem saya ( @array ) {
selanjutnya jika $seen{ $elem }++;
tekan @unik, $elem;
}
Anda dapat menulis ini lebih singkat menggunakan grep, yang melakukan hal yang sama.
%terlihat saya = ();
saya @unik = grep { ! $dilihat{ $_ }++ } @array;
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mengatakan apakah a tertentu elemen is berisi in a daftar or Himpunan?
(sebagian dari jawaban ini disumbangkan oleh Anno Siegel dan brian d foy)
Mendengar kata "dalam" adalah sebuah inindikasi bahwa Anda mungkin seharusnya menggunakan hash, bukan a
list atau larik, untuk menyimpan data Anda. Hash dirancang untuk menjawab pertanyaan ini dengan cepat dan
efisien. Array tidak.
Yang sedang berkata, ada beberapa cara untuk mendekati ini. Di Perl 5.10 dan yang lebih baru, Anda dapat
gunakan operator pencocokan pintar untuk memeriksa apakah suatu item terkandung dalam larik atau hash:
gunakan 5.010;
jika( $item ~~ @array ) {
katakan "Array berisi $item"
}
jika( $item ~~ %hash ) {
katakan "Hash berisi $item"
}
Dengan Perl versi sebelumnya, Anda harus melakukan sedikit lebih banyak pekerjaan. Jika Anda akan membuat
kueri ini berkali-kali pada nilai string arbitrer, cara tercepat mungkin adalah dengan membalikkan
array asli dan pertahankan hash yang kuncinya adalah nilai array pertama:
my @blues = qw/azure cerulean teal pirus lapis-lazuli/;
%is_blue saya = ();
untuk (@blues) { $is_blue{$_} = 1 }
Sekarang Anda dapat memeriksa apakah $is_blue{$some_color}. Mungkin ide yang bagus untuk tetap
blues semua dalam hash di tempat pertama.
Jika nilainya semua bilangan bulat kecil, Anda bisa menggunakan array berindeks sederhana. semacam ini
array akan memakan lebih sedikit ruang:
@prima saya = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
saya @is_tiny_prime = ();
untuk (@prima) { $is_tiny_prime[$_] = 1 }
# atau cukup @istiny_prime[@primes] = (1) x @prime;
Sekarang Anda memeriksa apakah $is_tiny_prime[$some_number].
Jika nilai yang dimaksud adalah bilangan bulat, bukan string, Anda dapat menyimpan cukup banyak
spasi dengan menggunakan string bit sebagai gantinya:
@artikel saya = ( 1..10, 150..2000, 2017 );
undef $baca;
untuk (@artikel) { vec($read,$_,1) = 1 }
Sekarang periksa apakah "vec($read,$n,1)" benar untuk beberapa $n.
Metode ini menjamin tes individu yang cepat tetapi memerlukan pengaturan ulang
daftar atau larik asli. Mereka hanya terbayar jika Anda harus menguji beberapa nilai terhadap
array yang sama.
Jika Anda menguji hanya sekali, modul standar List::Util mengekspor fungsi "pertama"
untuk tujuan ini. Ia bekerja dengan berhenti setelah menemukan elemen. Ini ditulis dalam C untuk
speed, dan padanan Perl-nya terlihat seperti subrutin ini:
sub pertama (&@) {
$kode saya = shift;
untuk setiap (@_) {
kembalikan $_ jika &{$kode}();
}
tidak jelas;
}
Jika kecepatan tidak terlalu diperhatikan, idiom umum menggunakan grep dalam konteks skalar (yang mengembalikan
jumlah item yang melewati kondisinya) untuk melintasi seluruh daftar. Ini memiliki
manfaat memberi tahu Anda berapa banyak kecocokan yang ditemukannya.
my $is_there = grep $_ eq $apapun, @array;
Jika Anda ingin benar-benar mengekstrak elemen yang cocok, cukup gunakan grep dalam konteks daftar.
@kecocokan saya = grep $_ eq $terserah, @array;
Seterpercayaapakah Olymp Trade? Kesimpulan do I menghitung itu perbedaan of dua array? Seterpercayaapakah Olymp Trade? Kesimpulan do I menghitung itu persimpangan of dua
array?
Gunakan hash. Berikut kode untuk melakukan keduanya dan banyak lagi. Diasumsikan bahwa setiap elemen unik dalam
array yang diberikan:
saya (@union, @intersection, @difference);
%hitungan saya = ();
foreach $elemen saya (@array1, @array2) { $count{$element}++ }
foreach $elemen saya (kunci %count) {
dorong @union, $elemen;
dorong @{ $hitung{$elemen} > 1 ? \@intersection : \@difference }, $elemen;
}
Perhatikan bahwa ini adalah simetris perbedaan, yaitu, semua elemen baik di A atau di B tetapi
tidak di keduanya. Anggap saja sebagai operasi xor.
Seterpercayaapakah Olymp Trade? Kesimpulan do I uji apakah dua array or hash adalah setara?
Dengan Perl 5.10 dan yang lebih baru, operator pertandingan pintar dapat memberi Anda jawaban paling sedikit
jumlah pekerjaan:
gunakan 5.010;
jika( @array1 ~~ @array2 ) {
say "Arraynya sama";
}
if( %hash1 ~~ %hash2 ) # tidak memeriksa nilai! {
katakan "Kunci hashnya sama";
}
Kode berikut berfungsi untuk array level tunggal. Ini menggunakan perbandingan string, dan
tidak membedakan string kosong yang ditentukan dan yang tidak ditentukan. Ubah jika Anda memiliki yang lain
kebutuhan.
$are_equal = bandingkan_arrays(\@katak, \@kodok);
sub bandingkan_array {
saya ($pertama, $kedua) = @_;
tidak ada peringatan; # diam palsu -w keluhan undef
kembali 0 kecuali @$pertama == @$kedua;
untuk ($i saya = 0; $i < @$pertama; $i++) {
kembalikan 0 jika $pertama->[$i] ne $kedua->[$i];
}
1 kembali;
}
Untuk struktur bertingkat, Anda mungkin ingin menggunakan pendekatan yang lebih seperti ini. Ini menggunakan
Modul CPAN FreezeThaw:
gunakan FreezeThaw qw(cmpStr);
my @a = my @b = ( "ini", "itu", [ "lebih", "barang" ] );
printf "a dan b berisi %s array\n",
cmpStr(\@a, \@b) == 0
? "sama"
: "berbeda";
Pendekatan ini juga berfungsi untuk membandingkan hash. Di sini kami akan menunjukkan dua yang berbeda
jawaban:
gunakan FreezeThaw qw(cmpStr cmpStrHard);
%a saya = %b saya = ( "ini" => "itu", "ekstra" => [ "lebih", "barang" ] );
$a{EKSTRASI} = \%b;
$b{EKSTRA} = \%a;
printf "a dan b mengandung %s hash\n",
cmpStr(\%a, \%b) == 0 ? "sama" : "berbeda";
printf "a dan b mengandung %s hash\n",
cmpStrHard(\%a, \%b) == 0 ? "sama" : "berbeda";
Yang pertama melaporkan bahwa kedua hash tersebut berisi data yang sama, sedangkan yang kedua
melaporkan bahwa mereka tidak melakukannya. Yang Anda sukai diserahkan sebagai latihan kepada pembaca.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menemukan itu pertama susunan elemen untuk yang a kondisi is benar?
Untuk menemukan elemen array pertama yang memenuhi suatu kondisi, Anda dapat menggunakan "first()"
fungsi dalam modul Daftar::Util, yang dilengkapi dengan Perl 5.8. Contoh ini menemukan yang pertama
elemen yang mengandung "Perl".
gunakan Daftar::Util qw(pertama);
$elemen saya = pertama { /Perl/ } @array;
Jika Anda tidak dapat menggunakan List::Util, Anda dapat membuat loop Anda sendiri untuk melakukan hal yang sama. sekali kamu
temukan elemennya, Anda menghentikan loop dengan yang terakhir.
$ saya ditemukan;
foreach ( @array ) {
if( /Perl/ ) { $ditemukan = $_; terakhir }
}
Jika Anda menginginkan indeks array, gunakan fungsi "firstidx()" dari "List::MoreUtils":
gunakan List::MoreUtils qw(firstidx);
$index saya = firstidx { /Perl/ } @array;
Atau tulis sendiri, iterasi melalui indeks dan periksa elemen array di masing-masing
indeks sampai Anda menemukan yang memenuhi kondisi:
saya( $ditemukan, $indeks ) = ( undef, -1 );
untuk( $i = 0; $i < @array; $i++ ) {
jika( $array[$i] =~ /Perl/ ) {
$ditemukan = $array[$i];
$indeks = $i;
terakhir;
}
}
Seterpercayaapakah Olymp Trade? Kesimpulan do I menangani terkait daftar?
(disumbangkan oleh brian d foy)
Array Perl tidak memiliki ukuran tetap, jadi Anda tidak perlu daftar tertaut jika Anda hanya ingin
menambah atau menghapus item. Anda dapat menggunakan operasi array seperti "push", "pop", "shift",
"unshift", atau "sambatan" untuk melakukan itu.
Namun, terkadang, daftar tertaut dapat berguna dalam situasi di mana Anda ingin "membagi" dan
array sehingga Anda memiliki banyak array kecil alih-alih satu array besar. Anda dapat menyimpan array
lebih panjang dari indeks array terbesar Perl, kunci array yang lebih kecil secara terpisah di threaded
program, mengalokasikan lebih sedikit memori, atau memasukkan elemen dengan cepat di tengah rantai.
Steve Lembark membahas detailnya dalam pembicaraan YAPC::NA 2009 "Perly Linked Lists" (
<http://www.slideshare.net/lembark/perly-linked-lists> ), meskipun Anda bisa menggunakan miliknya
LinkedList::Modul tunggal.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menangani bundar daftar?
(disumbangkan oleh brian d foy)
Jika Anda ingin menggilir array tanpa henti, Anda dapat menaikkan modul indeks
jumlah elemen dalam array:
@array saya = qw( abc );
saya $i = 0;
sementara( 1 ) {
print $array[ $i++ % @array ], "\n";
terakhir jika $i > 20;
}
Anda juga dapat menggunakan Tie::Cycle untuk menggunakan skalar yang selalu memiliki elemen berikutnya dari
array melingkar:
gunakan Tie::Siklus;
ikat $siklus saya, 'Tie::Cycle', [ qw( FFFFFF 000000 FFFF00 ) ];
cetak $siklus; #FFFFFF
cetak $siklus; # 000000
cetak $siklus; #FFFF00
Array::Iterator::Circular membuat objek iterator untuk array melingkar:
gunakan Array::Iterator::Circular;
$color_iterator saya = Array::Iterator::Circular->new(
qw (merah hijau biru oranye)
);
depan ( 1 .. 20 ) {
print $color_iterator->berikutnya, "\n";
}
Seterpercayaapakah Olymp Trade? Kesimpulan do I kocokan an susunan secara acak?
Jika Anda telah menginstal Perl 5.8.0 atau yang lebih baru, atau jika Anda memiliki Scalar-List-Utils 1.03 atau
kemudian diinstal, Anda dapat mengatakan:
gunakan Daftar::Util 'shuffle';
@acak = acak(@daftar);
Jika tidak, Anda dapat menggunakan shuffle Fisher-Yates.
subfisher_yates_shuffle {
$deck saya = shift; # $deck adalah referensi ke array
kembali kecuali @$deck; # tidak boleh kosong!
$i saya = @$dek;
sementara (--$i) {
$j saya = int rand ($i+1);
@$tumpukan[$i,$j] = @$tumpukan[$j,$i];
}
}
# acak koleksi mpeg saya
#
@mpeg saya = ;
fisher_yates_shuffle( \@mpeg ); # mengacak @mpeg di tempat
cetak @mpeg;
Perhatikan bahwa implementasi di atas mengacak array di tempatnya, tidak seperti
"List::Util::shuffle()" yang mengambil daftar dan mengembalikan daftar acak baru.
Anda mungkin pernah melihat algoritme pengacakan yang bekerja menggunakan sambungan, memilih yang lain secara acak
elemen untuk menukar elemen saat ini dengan
pasir;
@baru =();
@lama = 1 .. 10; # hanya demo
sementara (@lama) {
push(@baru, sambatan(@lama, rand @lama, 1));
}
Ini buruk karena sambungan sudah O(N), dan karena Anda melakukannya N kali, Anda baru saja menemukan
algoritma kuadrat; yaitu, O(N**2). Ini tidak berskala, meskipun Perl begitu
efisien sehingga Anda mungkin tidak akan menyadarinya sampai Anda memiliki array yang agak besar.
Seterpercayaapakah Olymp Trade? Kesimpulan do I proses/modifikasi setiap elemen of an Himpunan?
Gunakan "untuk"/"foreach":
untuk (@baris) {
s/foo/bar/; #ubah kata itu
tr/XZ/ZX/; # tukar huruf-huruf itu
}
Ini yang lain; mari kita hitung volume bola:
@volume saya = @radii;
for (@volumes) { # @volumes telah mengubah bagian
$_ **= 3;
$_ *= (4/3) * 3.14159; # ini akan terus dilipat
}
yang juga dapat dilakukan dengan "map()" yang dibuat untuk mengubah satu daftar menjadi yang lain:
@volume saya = peta {$_ ** 3 * (4/3) * 3.14159} @radii;
Jika Anda ingin melakukan hal yang sama untuk mengubah nilai hash, Anda dapat menggunakan
fungsi "nilai". Pada Perl 5.6 nilainya tidak disalin, jadi jika Anda memodifikasi $orbit (dalam
kasus ini), Anda mengubah nilainya.
untuk $orbit saya ( nilai %orbits ) {
($orbit **= 3) *= (4/3) * 3.14159;
}
Sebelum Perl 5.6 "nilai" mengembalikan salinan nilai, jadi sering kali kode perl yang lebih lama
berisi konstruksi seperti @orbits{keys %orbits} alih-alih "nilai %orbits" di mana
hash harus dimodifikasi.
Seterpercayaapakah Olymp Trade? Kesimpulan do I memilih a acak elemen dari an Himpunan?
Gunakan fungsi "rand()" (lihat "rand" di perlfunc):
$indeks saya = rand @array;
$elemen saya = $array[$index];
Atau, cukup:
$elemen saya = $array[ Rand @array ];
Seterpercayaapakah Olymp Trade? Kesimpulan do I menukar urutan N elemen of a daftar?
Gunakan modul List::Permutor di CPAN. Jika daftar sebenarnya adalah array, coba
Algoritma::Permute modul (juga di CPAN). Itu ditulis dalam kode XS dan sangat efisien:
gunakan Algoritma::Permute;
@array saya = 'a'..'d';
$p_iterator saya = Algoritma::Permute->new ( \@array );
while (@perm saya = $p_iterator->berikutnya) {
print "permutasi berikutnya: (@perm)\n";
}
Untuk eksekusi yang lebih cepat, Anda dapat melakukan:
gunakan Algoritma::Permute;
@array saya = 'a'..'d';
Algoritma::Permute::permute {
print "permutasi berikutnya: (@array)\n";
} @Himpunan;
Berikut adalah program kecil yang menghasilkan semua permutasi dari semua kata pada setiap baris
memasukkan. Algoritme yang terkandung dalam fungsi "permute()" dibahas dalam Volume 4 (masih
tidak diterbitkan) dari Knuth's Seni of komputer Pemrograman dan akan bekerja pada daftar apa pun:
#!/usr/bin/Perl -n
# Fischer-Krause memerintahkan generator permutasi
sub permutasi (&@) {
$kode saya = shift;
@idx saya = 0..$#_;
while ( $code->(@_[@idx]) ) {
$p saya = $#idx;
--$p while $idx[$p-1] > $idx[$p];
$q saya = $p atau kembali;
push @idx, sambatan terbalik @idx, $p;
++$q while $idx[$p-1] > $idx[$q];
@idx[$p-1,$q]=@idx[$q,$p-1];
}
}
permute { cetak "@_\n" } split;
Modul Algorithm::Loops juga menyediakan fungsi "NextPermute" dan "NextPermuteNum"
yang secara efisien menemukan semua permutasi unik dari sebuah array, bahkan jika itu berisi duplikat
nilai, memodifikasinya di tempat: jika elemennya dalam urutan terbalik maka array
dibalik, membuatnya diurutkan, dan mengembalikan false; jika tidak, permutasi berikutnya adalah
dikembalikan.
"NextPermute" menggunakan urutan string dan urutan numerik "NextPermuteNum", sehingga Anda dapat menghitung
semua permutasi dari 0..9 seperti ini:
gunakan Algoritma::Loops qw(NextPermuteNum);
@daftar saya= 0;
lakukan { print "@list\n" } while NextPermuteNum @list;
Seterpercayaapakah Olymp Trade? Kesimpulan do I jenis an susunan by (apa pun)?
Berikan fungsi perbandingan ke menyortir() (dijelaskan dalam "sort" di perlfunc):
@daftar = sort { $a <=> $b } @daftar;
Fungsi sortir default adalah cmp, perbandingan string, yang akan mengurutkan "(1, 2, 10)" menjadi
"(1, 10, 2)". "<=>", digunakan di atas, adalah operator perbandingan numerik.
Jika Anda memiliki fungsi rumit yang diperlukan untuk mengeluarkan bagian yang ingin Anda urutkan, maka
jangan lakukan itu di dalam fungsi sortir. Tarik keluar dulu, karena sortir BLOK bisa
dipanggil berkali-kali untuk elemen yang sama. Berikut ini contoh cara mencabut yang pertama
kata setelah angka pertama pada setiap item, dan kemudian urutkan kata-kata tersebut dengan tidak peka huruf besar/kecil.
@idx saya;
untuk (@data) {
$barang saya;
($item) = /\d+\s*(\S+)/;
tekan @idx, uc($item);
}
@sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ];
yang juga bisa ditulis dengan cara ini, menggunakan trik yang kemudian dikenal sebagai
Transformasi Schwartzian:
@sorted saya = peta { $_->[0] }
sort { $a->[1] cmp $b->[1] }
peta { [ $_, uc( (/\d+\s*(\S+)/)[0]) ] } @data;
Jika Anda perlu mengurutkan pada beberapa bidang, paradigma berikut berguna.
saya @sorted = sort {
bidang1($a) <=> bidang1($b) ||
bidang2($a) cmp bidang2($b) ||
bidang3($a) cmp bidang3($b)
} @data;
Ini dapat dengan mudah dikombinasikan dengan pra-perhitungan kunci seperti yang diberikan di atas.
Lihat jenis artikel dalam koleksi "Jauh Lebih Dari Yang Pernah Ingin Anda Ketahui" di
<http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz> untuk lebih lanjut tentang pendekatan ini.
Lihat juga pertanyaan nanti di perlfaq4 tentang menyortir hash.
Seterpercayaapakah Olymp Trade? Kesimpulan do I memanipulasi array of sedikit?
Gunakan "pack()" dan "unpack()", atau "vec()" dan operasi bitwise.
Misalnya, Anda tidak perlu menyimpan bit individu dalam array (yang berarti bahwa
Anda membuang banyak ruang). Untuk mengonversi larik bit menjadi string, gunakan "vec()" untuk
mengatur bit yang tepat. Ini menetapkan $vec agar bit N disetel hanya jika $ints[N] disetel:
saya @ints = (...); # array bit, misalnya ( 1, 0, 0, 1, 1, 0 ... )
$vec saya = '';
foreach( 0 .. $#ints ) {
vec($vec,$_,1) = 1 jika $ints[$_];
}
String $vec hanya membutuhkan bit sebanyak yang dibutuhkan. Misalnya, jika Anda memiliki 16
entri di @ints, $vec hanya membutuhkan dua byte untuk menyimpannya (tidak termasuk skalar
overhead variabel).
Begini caranya, dengan vektor di $vec, Anda bisa memasukkan bit-bit itu ke dalam larik @ints Anda:
sub bitvec_to_list {
$vec saya = shift;
@ints saya;
# Temukan kepadatan byte nol lalu pilih algoritma terbaik
if ($vec =~ tr/\0// / panjang $vec > 0.95) {
gunakan bilangan bulat;
saya $i;
# Metode ini lebih cepat dengan sebagian besar null-byte
while($vec =~ /[^\0]/g ) {
$i = -9 + 8 * pos $vec;
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
tekan @ints, $i jika vec($vec, ++$i, 1);
}
}
else {
# Metode ini adalah algoritma umum yang cepat
gunakan bilangan bulat;
my $bits = membongkar "b*", $vec;
tekan @ints, 0 jika $bit =~ s/^(\d)// && $1;
tekan @ints, pos $bits while($bits =~ /1/g);
}
kembali \@ints;
}
Metode ini semakin cepat semakin jarang vektor bitnya. (Courtesy dari Tim Bunce dan
Winfried Koenig.)
Anda dapat membuat perulangan while jauh lebih pendek dengan saran dari Benjamin Goldberg ini:
while($vec =~ /[^\0]+/g ) {
tekan @ints, grep vec($vec, $_, 1), $-[0] * 8 .. $+[0] * 8;
}
Atau gunakan modul CPAN Bit::Vector:
$vektor saya = Bit::Vector->new($num_of_bits);
$vektor->Index_List_Store(@ints);
@ints saya = $vektor->Index_List_Read();
Bit::Vector menyediakan metode yang efisien untuk bit vector, himpunan bilangan bulat kecil dan "besar
int" matematika.
Berikut ilustrasi yang lebih luas menggunakan vektor():
# demo vec
$vektor saya = "\xff\x0f\xef\xfe";
print "String Ilya \\xff\\x0f\\xef\\xfe mewakili angka ",
membongkar("N", $vektor), "\n";
$is_set saya = vec($vektor, 23, 1);
print "Bit ke-23nya adalah ", $is_set ? "set" : "hapus", ".\n";
pvec($vektor);
set_vec(1,1,1);
set_vec(3,1,1);
set_vec(23,1,1);
set_vec(3,1,3);
set_vec(3,2,3);
set_vec(3,4,3);
set_vec(3,4,7);
set_vec(3,8,3);
set_vec(3,8,7);
set_vec(0,32,17);
set_vec(1,32,17);
subset_vec {
saya ($offset, $lebar, $nilai) = @_;
$vektor saya = '';
vec($vektor, $offset, $lebar) = $nilai;
print "offset=$offset lebar=$nilai lebar=$nilai\n";
pvec($vektor);
}
sub pvc {
$vektor saya = shift;
my $bits = unpack("b*", $vector);
saya $i = 0;
$BASE saya = 8;
print "panjang vektor dalam byte: ", panjang($vektor), "\n";
@byte = unpack("A8" x panjang($vektor), $bit);
print "bit adalah: @byte\n\n";
}
Mengapa tidak didefinisikan() kembali benar on kosong array dan hash?
Cerita pendeknya adalah Anda mungkin hanya menggunakan definisi pada skalar atau fungsi, bukan
pada agregat (array dan hash). Lihat "didefinisikan" di perlfunc dalam rilis 5.004 atau yang lebih baru
dari Perl untuk lebih jelasnya.
Tanggal: Hash (Asosiatif Array)
Seterpercayaapakah Olymp Trade? Kesimpulan do I proses an seluruh hash?
(disumbangkan oleh brian d foy)
Ada beberapa cara untuk memproses seluruh hash. Anda bisa mendapatkan daftar
kunci, lalu buka setiap kunci, atau ambil satu pasangan nilai kunci sekaligus.
Untuk menelusuri semua tombol, gunakan fungsi "tombol". Ini mengekstrak semua kunci dari
hash dan mengembalikannya kepada Anda sebagai daftar. Anda kemudian bisa mendapatkan nilainya melalui
kunci tertentu yang Anda proses:
foreach my $key ( kunci %hash ) {
$nilai saya = $hash{$key}
...
}
Setelah Anda memiliki daftar kunci, Anda dapat memproses daftar itu sebelum Anda memproses hash
elemen. Misalnya, Anda dapat mengurutkan kunci sehingga Anda dapat memprosesnya dalam urutan leksikal:
foreach $key saya ( urutkan kunci %hash ) {
$nilai saya = $hash{$key}
...
}
Atau, Anda mungkin hanya ingin memproses beberapa item. Jika Anda hanya ingin berurusan dengan
kunci yang dimulai dengan "teks:", Anda dapat memilih hanya yang menggunakan "grep":
foreach $key saya ( grep /^text:/, kunci %hash ) {
$nilai saya = $hash{$key}
...
}
Jika hash sangat besar, Anda mungkin tidak ingin membuat daftar kunci yang panjang. Untuk menyimpan beberapa
memori, Anda dapat mengambil satu pasangan nilai kunci sekaligus menggunakan "each()", yang mengembalikan pasangan Anda
belum melihat:
while( saya( $kunci, $nilai ) = masing-masing( %hash ) ) {
...
}
Operator "setiap" mengembalikan pasangan dalam urutan yang tampaknya acak, jadi jika pemesanan itu penting
untuk Anda, Anda harus tetap menggunakan metode "kunci".
Operator "each()" bisa sedikit rumit. Anda tidak dapat menambah atau menghapus kunci hash
saat Anda menggunakannya tanpa mungkin melewatkan atau memproses ulang beberapa pasangan setelah Perl
secara internal mengulangi semua elemen. Selain itu, hash hanya memiliki satu iterator, jadi jika
Anda mencampur "kunci", "nilai", atau "masing-masing" pada hash yang sama, Anda berisiko mengatur ulang iterator dan
mengacaukan pemrosesan Anda. Lihat entri "setiap" di perlfunc untuk detail lebih lanjut.
Seterpercayaapakah Olymp Trade? Kesimpulan do I bergabung dua hash?
(disumbangkan oleh brian d foy)
Sebelum Anda memutuskan untuk menggabungkan dua hash, Anda harus memutuskan apa yang harus dilakukan jika kedua hash
berisi kunci yang sama dan jika Anda ingin membiarkan hash asli apa adanya.
Jika Anda ingin mempertahankan hash asli, salin satu hash (%hash1) ke hash baru
(%new_hash), lalu tambahkan kunci dari hash lain (%hash2 ke hash baru. Memeriksa itu
kunci sudah ada di %new_hash memberi Anda kesempatan untuk memutuskan apa yang harus dilakukan dengan
duplikat:
%new_hash saya = %hash1; # membuat salinan; tinggalkan %hash1 sendiri
foreach $key2 saya ( kunci %hash2 ) {
if( ada $new_hash{$key2} ) {
warning "Kunci [$key2] ada di kedua hash!";
# menangani duplikat (mungkin hanya peringatan)
...
Selanjutnya;
}
else {
$hash_baru{$key2} = $hash2{$key2};
}
}
Jika Anda tidak ingin membuat hash baru, Anda masih dapat menggunakan teknik perulangan ini; hanya
ubah %new_hash menjadi %hash1.
foreach $key2 saya ( kunci %hash2 ) {
if( ada $hash1{$key2} ) {
warning "Kunci [$key2] ada di kedua hash!";
# menangani duplikat (mungkin hanya peringatan)
...
Selanjutnya;
}
else {
$hash1{$kunci2} = $hash2{$kunci2};
}
}
Jika Anda tidak peduli bahwa satu hash menimpa kunci dan nilai dari yang lain, Anda bisa
gunakan irisan hash untuk menambahkan satu hash ke hash lainnya. Dalam hal ini, nilai dari %hash2 menggantikan
nilai dari %hash1 ketika mereka memiliki kunci yang sama:
@hash1{ kunci %hash2 } = nilai %hash2;
Apa Terjadi if I menambahkan or menghapus kunci-kunci dari a hash sementara iterasi lebih saya t?
(disumbangkan oleh brian d foy)
Jawaban mudahnya adalah "Jangan lakukan itu!"
Jika Anda mengulangi melalui hash dengan setiap(), Anda dapat menghapus kunci yang baru saja dikembalikan
tanpa mengkhawatirkannya. Jika Anda menghapus atau menambahkan kunci lain, iterator dapat melewati atau
gandakan mereka karena Perl dapat mengatur ulang tabel hash. Lihat entri untuk "setiap ()" di
perfunc.
Seterpercayaapakah Olymp Trade? Kesimpulan do I melihat up a hash elemen by nilai?
Buat hash terbalik:
%by_value saya = membalikkan %by_key;
$kunci saya = $berdasarkan nilai{$nilai};
Itu tidak terlalu efisien. Akan lebih hemat ruang untuk menggunakan:
while (my ($key, $value) = masing-masing %by_key) {
$oleh_nilai{$nilai} = $kunci;
}
Jika hash Anda dapat memiliki nilai berulang, metode di atas hanya akan menemukan salah satu dari
kunci terkait. Ini mungkin atau mungkin tidak membuat Anda khawatir. Jika itu membuatmu khawatir, kamu selalu bisa
membalikkan hash menjadi hash array sebagai gantinya:
while (my ($key, $value) = masing-masing %by_key) {
tekan @{$key_list_by_value{$value}}, $key;
}
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I tahu bagaimana banyak entri adalah in a hash?
(disumbangkan oleh brian d foy)
Ini sangat mirip dengan "Bagaimana cara memproses seluruh hash?", Juga di perlfaq4, tapi sedikit
sederhana dalam kasus umum.
Anda dapat menggunakan fungsi bawaan "keys()" dalam konteks skalar untuk mengetahui apakah ada banyak entri
yang Anda miliki dalam hash:
$key_count saya = kunci %hash; # harus konteks skalar!
Jika Anda ingin mengetahui berapa banyak entri yang memiliki nilai yang ditentukan, itu sedikit berbeda. Anda
harus memeriksa setiap nilai. "grep" berguna:
my $defined_value_count = grep { didefinisikan } nilai %hash;
Anda dapat menggunakan struktur yang sama untuk menghitung entri dengan cara apa pun yang Anda suka. jika kamu mau
hitungan kunci dengan vokal di dalamnya, Anda cukup mengujinya sebagai gantinya:
my $vowel_count = kunci grep { /[aeiou]/ } %hash;
"grep" dalam konteks skalar mengembalikan hitungan. Jika Anda ingin daftar item yang cocok,
gunakan saja dalam konteks daftar sebagai gantinya:
my @defined_values = grep { didefinisikan } nilai %hash;
Fungsi "keys()" juga mengatur ulang iterator, yang berarti Anda mungkin melihat hal yang aneh
hasil jika Anda menggunakan ini di antara penggunaan operator hash lain seperti "each()".
Seterpercayaapakah Olymp Trade? Kesimpulan do I jenis a hash (opsional by nilai sebagai gantinya of kunci)?
(disumbangkan oleh brian d foy)
Untuk mengurutkan hash, mulailah dengan kunci. Dalam contoh ini, kami memberikan daftar kunci untuk pengurutan
fungsi yang kemudian membandingkannya secara ASCIIbetis (yang mungkin dipengaruhi oleh lokal Anda
pengaturan). Daftar keluaran memiliki kunci dalam urutan ASCIIbetical. Setelah kami memiliki kuncinya, kami
dapat melaluinya untuk membuat laporan yang mencantumkan kunci dalam urutan ASCIIbetical.
@keys saya = urutkan { $a cmp $b } kunci %hash;
cari $key saya ( @keys ) {
printf "%-20s %6d\n", $kunci, $hash{$kunci};
}
Kita bisa menjadi lebih mewah di blok "sort()". Alih-alih membandingkan kunci, kami
dapat menghitung nilai dengan mereka dan menggunakan nilai itu sebagai perbandingan.
Misalnya, untuk membuat urutan laporan tidak peka huruf besar/kecil, kami menggunakan "lc" untuk huruf kecil pada tombol
sebelum membandingkannya:
my @keys = sort { lc $a cmp lc $b } kunci %hash;
Catatan: jika perhitungannya mahal atau hash memiliki banyak elemen, Anda mungkin ingin melihat
di Transformasi Schwartzian untuk menyimpan hasil komputasi.
Jika kita ingin mengurutkan berdasarkan nilai hash, kita menggunakan kunci hash untuk mencarinya. Kita masih
keluar daftar kunci, tapi kali ini mereka diurutkan berdasarkan nilainya.
my @keys = sort { $hash{$a} <=> $hash{$b} } kunci %hash;
Dari sana kita bisa menjadi lebih kompleks. Jika nilai hashnya sama, kami dapat memberikan
sortir sekunder pada kunci hash.
@keys saya = urutkan {
$hash{$a} <=> $hash{$b}
or
"\L$a" cmp "\L$b"
} kunci %hash;
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I selalu menjaga my hash diurutkan?
Anda dapat melihat menggunakan modul "DB_File" dan "tie()" menggunakan ikatan hash $DB_BTREE
seperti yang didokumentasikan dalam "In Memory Databases" di DB_File. Modul Tie::IxHash dari CPAN mungkin
juga menjadi instruktif. Meskipun ini membuat hash Anda tetap diurutkan, Anda mungkin tidak menyukai
perlambatan Anda menderita dari antarmuka dasi. Apakah Anda yakin perlu melakukan ini? :)
Apa itu perbedaan antara "menghapus" dan "tidak pasti" dengan hash?
Hash berisi pasangan skalar: yang pertama adalah kuncinya, yang kedua adalah nilainya. Kunci
akan dipaksakan ke string, meskipun nilainya dapat berupa skalar apa pun: string, angka,
atau referensi. Jika kunci $key ada di %hash, "exists($hash{$key})" akan mengembalikan nilai true.
Nilai untuk kunci yang diberikan dapat berupa "undef", dalam hal ini $hash{$key} akan menjadi "undef" sementara
"exists $hash{$key}" akan mengembalikan nilai true. Ini sesuai dengan ($key, "undef") berada di
hash.
Gambar membantu... Berikut tabel %hash:
nilai kunci
+------+------+
| sebuah | 3 |
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
Dan kondisi ini berlaku
$hash{'a'} benar
$hash{'d'} salah
didefinisikan $hash{'d'} benar
didefinisikan $hash{'a'} benar
ada $hash{'a'} benar (hanya Perl 5)
grep ($_ eq 'a', kunci %hash) benar
Jika Anda sekarang mengatakan
undef $hash{'a'}
tabel Anda sekarang berbunyi:
nilai kunci
+------+------+
| sebuah | undef|
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
dan kondisi ini sekarang berlaku; perubahan topi:
$hash{'a'} adalah SALAH
$hash{'d'} salah
didefinisikan $hash{'d'} benar
didefinisikan $hash{'a'} adalah SALAH
ada $hash{'a'} benar (hanya Perl 5)
grep ($_ eq 'a', kunci %hash) benar
Perhatikan dua yang terakhir: Anda memiliki nilai undef, tetapi kunci yang ditentukan!
Sekarang, pertimbangkan ini:
hapus $hash{'a'}
tabel Anda sekarang berbunyi:
nilai kunci
+------+------+
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
dan kondisi ini sekarang berlaku; perubahan topi:
$hash{'a'} salah
$hash{'d'} salah
didefinisikan $hash{'d'} benar
didefinisikan $hash{'a'} salah
ada $hash{'a'} adalah FALSE (hanya Perl 5)
grep ($_ eq 'a', kunci %hash) adalah SALAH
Lihat, seluruh entri hilang!
Mengapa tidak my diikat hash membuat itu ditentukan/ada perbedaan?
Ini tergantung pada implementasi hash terikat dari ADA(). Misalnya, tidak ada
konsep undef dengan hash yang terkait dengan file DBM*. Ini juga berarti bahwa ada() dan
didefinisikan() melakukan hal yang sama dengan file DBM*, dan apa yang akhirnya mereka lakukan bukanlah yang mereka lakukan
lakukan dengan hash biasa.
Seterpercayaapakah Olymp Trade? Kesimpulan do I ulang an setiap() operasi setengah jalan melalui?
(disumbangkan oleh brian d foy)
Anda dapat menggunakan fungsi "kunci" atau "nilai" untuk mengatur ulang "setiap". Untuk hanya mengatur ulang iterator
digunakan oleh "setiap" tanpa melakukan hal lain, gunakan salah satunya dalam konteks batal:
kunci %hash; # mengatur ulang iterator, tidak ada yang lain.
nilai %hash; # mengatur ulang iterator, tidak ada yang lain.
Lihat dokumentasi untuk "setiap" di perlfunc.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mendapatkan itu unik kunci-kunci dari dua hash?
Pertama Anda mengekstrak kunci dari hash ke dalam daftar, lalu selesaikan "menghapus
duplikat" masalah yang dijelaskan di atas. Misalnya:
%terlihat saya = ();
untuk $elemen saya (keys(%foo), keys(%bar)) {
$terlihat{$elemen}++;
}
saya @uniq = kunci %seen;
Atau lebih ringkasnya:
saya @uniq = kunci %{{%foo,%bar}};
Atau jika Anda benar-benar ingin menghemat ruang:
%terlihat saya = ();
while (didefinisikan ($kunci = setiap %foo)) {
$terlihat{$kunci}++;
}
while (didefinisikan ($key = setiap %bar)) {
$terlihat{$kunci}++;
}
saya @uniq = kunci %seen;
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I menyimpan a multidimensi susunan in a DBM mengajukan?
Buat strukturnya sendiri (tidak menyenangkan), atau dapatkan MLDBM (yang menggunakan
Data::Dumper) modul dari CPAN dan letakkan di atas DB_File atau GDBM_File. Anda
mungkin juga mencoba DBM::Deep, tetapi bisa agak lambat.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I membuat my hash ingat itu urutan I menempatkan elemen ke saya t?
Gunakan Tie::IxHash dari CPAN.
gunakan Tie::IxHash;
ikat %myhash saya, 'Tie::IxHash';
untuk ($i=0 saya; $i<20; $i++) {
$hash saya{$i} = 2*$i;
}
@keys saya = kunci %myhash;
# @kunci = (0,1,2,3,...)
Mengapa tidak lewat a subrutin an tidak terdefinisi elemen in a hash membuat saya t?
(disumbangkan oleh brian d foy)
Apakah Anda menggunakan Perl versi lama?
Biasanya, mengakses nilai kunci hash untuk kunci yang tidak ada akan tidak membuat kunci.
%hash saya = ();
$nilai saya = $hash{ 'foo' };
print "Ini tidak akan dicetak\n" jika ada $hash{ 'foo' };
Melewati $hash{ 'foo' } ke subrutin dulunya merupakan kasus khusus. Karena kamu bisa
menetapkan langsung ke $_[0], Perl harus siap untuk membuat tugas itu sehingga menciptakan
kunci hash sebelumnya:
my_sub( $hash{ 'foo' } );
print "Ini akan dicetak sebelum 5.004\n" jika ada $hash{ 'foo' };
sub saya_sub {
# $_[0] = 'bilah'; # buat kunci hash jika Anda melakukan ini
1;
}
Sejak Perl 5.004, bagaimanapun, situasi ini adalah kasus khusus dan Perl membuat kunci hash
hanya ketika Anda membuat tugas:
my_sub( $hash{ 'foo' } );
print "Ini akan dicetak, bahkan setelah 5.004\n" jika ada $hash{ 'foo' };
sub saya_sub {
$_[0] = 'bilah';
}
Namun, jika Anda menginginkan perilaku lama (dan pikirkan baik-baik karena itu aneh
efek samping), Anda dapat melewatkan irisan hash sebagai gantinya. Perl 5.004 tidak menjadikan ini spesial
kasus:
my_sub( @hash{ qw/foo/ } );
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I membuat itu Perl setara of a C struktur/C++ kelas/hash or susunan of hash or
array?
Biasanya hash ref, mungkin seperti ini:
$rekaman = {
NAMA => "Jason",
EMPNO => 132,
JUDUL => "wakil prajurit",
USIA => 23,
GAJI => 37_000,
PALS => [ "Norbert", "Rhys", "Phineas"],
};
Referensi didokumentasikan dalam perlref dan perlreftut. Contoh struktur data yang kompleks
diberikan dalam perldsc dan perllol. Contoh struktur dan kelas berorientasi objek adalah
di perlootut.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I menggunakan a referensi as a hash kunci?
(disumbangkan oleh brian d foy dan Ben Morrow)
Kunci hash adalah string, jadi Anda tidak dapat benar-benar menggunakan referensi sebagai kunci. Ketika Anda mencoba melakukannya
bahwa, Perl mengubah referensi menjadi bentuk string (misalnya,
"HASH(0xDEADBEEF)"). Dari sana Anda tidak bisa mendapatkan kembali referensi dari stringified
bentuk, setidaknya tanpa melakukan pekerjaan ekstra sendiri.
Ingat bahwa entri dalam hash akan tetap ada meskipun variabel yang direferensikan
keluar dari ruang lingkup, dan sangat mungkin bagi Perl untuk selanjutnya mengalokasikan a
variabel yang berbeda pada alamat yang sama. Ini berarti variabel baru mungkin secara tidak sengaja
dikaitkan dengan nilai untuk yang lama.
Jika Anda memiliki Perl 5.10 atau lebih baru, dan Anda hanya ingin menyimpan nilai terhadap referensi
untuk pencarian nanti, Anda dapat menggunakan modul inti Hash::Util::Fieldhash. Ini juga akan menangani
mengganti nama kunci jika Anda menggunakan banyak utas (yang menyebabkan semua variabel menjadi
dialokasikan kembali di alamat baru, mengubah stringifikasinya), dan mengumpulkan sampah
entri ketika variabel yang direferensikan keluar dari ruang lingkup.
Jika Anda benar-benar harus bisa mendapatkan referensi nyata kembali dari setiap entri hash, Anda bisa
gunakan modul Tie::RefHash, yang melakukan pekerjaan yang diperlukan untuk Anda.
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I memeriksa if a kunci ada in a bertingkat hash?
(disumbangkan oleh brian d foy)
Trik untuk masalah ini adalah menghindari autovivifikasi yang tidak disengaja. Jika Anda ingin memeriksa
tiga kunci dalam, Anda mungkin dengan naif mencoba ini:
%hash saya;
if( ada $hash{key1}{key2}{key3} ) {
...;
}
Meskipun Anda memulai dengan hash yang benar-benar kosong, setelah panggilan ke "ada", Anda telah
membuat struktur yang Anda butuhkan untuk memeriksa "key3":
%has = (
'kunci1' => {
'key2' => {}
}
);
Itu autovivifikasi. Anda dapat menyiasatinya dengan beberapa cara. Cara termudah adalah dengan
matikan. Pragma "autovivifikasi" leksikal tersedia di CPAN. Sekarang Anda tidak menambahkan
ke hash:
{
tidak ada autovivifikasi;
%hash saya;
if( ada $hash{key1}{key2}{key3} ) {
...;
}
}
Modul Data::Diver di CPAN juga dapat melakukannya untuk Anda. Subrutin "Menyelam"-nya dapat memberi tahu Anda
tidak hanya jika kunci ada tetapi juga mendapatkan nilai:
gunakan Data::Penyelam qw(Menyelam);
@exists saya = Menyelam( \%hash, qw(key1 key2 key3) );
jika( ! @ada ) {
...; # kunci tidak ada
}
elsif( ! didefinisikan $exists[0] ) {
...; # kunci ada tetapi nilainya tidak undef
}
Anda juga dapat melakukannya sendiri dengan mudah dengan memeriksa setiap level hash sebelum Anda pindah
ke tingkat berikutnya. Inilah yang dilakukan Data::Diver untuk Anda:
jika( check_hash( \%hash, qw(kunci1 kunci2 kunci3) ) ) {
...;
}
sub check_hash {
saya( $hash, @keys ) = @_;
kembali kecuali @keys;
cari $key saya ( @keys ) {
return kecuali eval { ada $hash->{$key} };
$hash = $hash->{$key};
}
1 kembali;
}
Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mencegah tambahan of tidak diinginkan kunci-kunci ke a hash?
Sejak versi 5.8.0, hash dapat menjadi terbatas ke sejumlah kunci yang diberikan. Metode untuk
membuat dan menangani hash terbatas diekspor oleh modul Hash::Util.
Tanggal: Lain-lain
Seterpercayaapakah Olymp Trade? Kesimpulan do I menangani biner data benar?
Perl bersih biner, sehingga dapat menangani data biner dengan baik. Pada Windows atau DOS, bagaimanapun,
anda harus menggunakan "binmode" untuk file biner untuk menghindari konversi untuk akhir baris. Di
umum, Anda harus menggunakan "binmode" setiap kali Anda ingin bekerja dengan data biner.
Lihat juga "binmode" di perlfunc atau perlopentut.
Jika Anda khawatir tentang data tekstual 8-bit, lihat perlllocale. Jika Anda ingin berurusan
dengan karakter multibyte, namun, ada beberapa gotcha. Lihat bagian Reguler
Ekspresi.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menentukan apakah a skalar is a nomor/seluruh/bilangan bulat/float?
Dengan asumsi bahwa Anda tidak peduli dengan notasi IEEE seperti "NaN" atau "Infinity", Anda mungkin
hanya ingin menggunakan ekspresi reguler:
gunakan 5.010;
diberikan( $angka ) {
ketika( /\D/ )
{ katakan "\ itu bukan angka"; melanjutkan }
ketika( /^\d+\z/ )
{ katakan "\ adalah bilangan bulat"; melanjutkan }
kapan( /^-?\d+\z/ )
{ katakan "\ adalah bilangan bulat"; melanjutkan }
kapan( /^[+-]?\d+\z/ )
{ katakan "\tis a +/- bilangan bulat"; melanjutkan }
kapan( /^-?(?:\d+\.?|\.\d)\d*\z/ )
{ katakan "\ adalah bilangan real"; melanjutkan }
kapan( /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i)
{ katakan "\ adalah pelampung C" }
}
Ada juga beberapa modul yang umum digunakan untuk tugas tersebut. Skalar::Util (didistribusikan dengan
5.8) menyediakan akses ke fungsi internal Perl "looks_like_number" untuk menentukan
apakah variabel terlihat seperti angka. Data::Mengetik fungsi ekspor yang memvalidasi data
jenis menggunakan ekspresi reguler di atas dan lainnya. Ketiga, ada Regexp::Common
yang memiliki ekspresi reguler untuk mencocokkan berbagai jenis angka. Ketiga modul tersebut adalah
tersedia dari CPAN.
Jika Anda menggunakan sistem POSIX, Perl mendukung fungsi "POSIX::strtod" untuk mengonversi
string menjadi ganda (dan juga "POSIX::strtol" untuk long). Semantiknya agak
rumit, jadi inilah fungsi pembungkus "getnum" untuk akses yang lebih nyaman. Ini
function mengambil string dan mengembalikan nomor yang ditemukan, atau "undef" untuk input yang bukan a
C mengapung. Fungsi "is_numeric" adalah ujung depan untuk "getnum" jika Anda hanya ingin mengatakan, "Is
ini pelampung?"
sub getnum {
gunakan POSIX qw(strtod);
$str saya = shift;
$str =~s/^\s+//;
$str =~ s/\s+$//;
$! = 0;
my($num, $belum diurai) = strtod($str);
if (($str eq '') || ($unparse != 0) || $!) {
kembali undef;
}
else {
kembali $jumlah;
}
}
sub is_numeric { didefinisikan getnum($_[0]) }
Atau Anda dapat memeriksa modul String::Scanf di CPAN sebagai gantinya.
Seterpercayaapakah Olymp Trade? Kesimpulan do I menjaga bersikeras data di seluruh program panggilan?
Untuk beberapa aplikasi tertentu, Anda dapat menggunakan salah satu modul DBM. Lihat AnyDBM_File. Lagi
secara umum, Anda harus berkonsultasi dengan modul FreezeThaw atau Storable dari CPAN. Mulai
dari Perl 5.8, Storable adalah bagian dari distribusi standar. Berikut salah satu contoh menggunakan
Fungsi "simpan" dan "ambil" yang dapat disimpan:
gunakan Dapat Disimpan;
toko(\%hash, "nama file");
# nanti...
$href = ambil("nama file"); # oleh ref
%hash = %{ ambil("nama file") }; # langsung ke hash
Seterpercayaapakah Olymp Trade? Kesimpulan do I mencetak di luar or salinan a rekursif data struktur?
Modul Data::Dumper pada CPAN (atau rilis 5.005 dari Perl) sangat bagus untuk dicetak
struktur data. Modul Storable pada CPAN (atau rilis Perl 5.8), menyediakan a
fungsi yang disebut "dclone" yang secara rekursif menyalin argumennya.
gunakan qw (dclone);
$r2 = kloning($r1);
Di mana $r1 dapat menjadi referensi untuk semua jenis struktur data yang Anda inginkan. Ini akan sangat dalam
disalin. Karena "dclone" mengambil dan mengembalikan referensi, Anda harus menambahkan tanda baca ekstra
jika Anda memiliki hash array yang ingin Anda salin.
%hash baru = %{ dclone(\%hash lama) };
Seterpercayaapakah Olymp Trade? Kesimpulan do I menetapkan metode untuk setiap kelas/objek?
(disumbangkan oleh Ben Morrow)
Anda dapat menggunakan kelas "UNIVERSAL" (lihat UNIVERSAL). Namun, harap berhati-hati untuk
pertimbangkan konsekuensi dari melakukan ini: menambahkan metode ke setiap objek sangat mungkin untuk
memiliki konsekuensi yang tidak diinginkan. Jika memungkinkan, akan lebih baik untuk memiliki semua objek Anda
mewarisi dari beberapa kelas dasar umum, atau menggunakan sistem objek seperti Moose yang mendukung
peran.
Seterpercayaapakah Olymp Trade? Kesimpulan do I memeriksa a kredit kartu checksum?
Dapatkan modul Business::CreditCard dari CPAN.
Seterpercayaapakah Olymp Trade? Kesimpulan do I pak array of ganda or mengapung untuk XS kode?
Kode arrays.h/arrays.c dalam modul PGPLOT di CPAN melakukan hal ini. Jika Anda melakukan
banyak pemrosesan float atau double, pertimbangkan untuk menggunakan modul PDL dari CPAN sebagai gantinya - itu
membuat angka-angka mudah.
Lihathttp://search.cpan.org/dist/PGPLOT> untuk kodenya.
PENULIS DAN HAK CIPTA
Hak Cipta (c) 1997-2010 Tom Christiansen, Nathan Torkington, dan penulis lain sebagaimana disebutkan.
Seluruh hak cipta.
Dokumentasi ini gratis; Anda dapat mendistribusikan ulang dan/atau memodifikasinya dengan persyaratan yang sama
sebagai Perl itu sendiri.
Terlepas dari distribusinya, semua contoh kode dalam file ini dengan ini ditempatkan di
domain publik. Anda diizinkan dan didorong untuk menggunakan kode ini dalam program Anda sendiri
untuk bersenang-senang atau untuk keuntungan sesuai keinginan Anda. Komentar sederhana dalam kode yang memberikan kredit adalah
sopan tapi tidak wajib.
Gunakan perlfaq4 online menggunakan layanan onworks.net