Cari array objek untuk mencocokkan kemungkinan beberapa nilai menggunakan operator perbandingan yang berbeda

Saya memiliki fungsi untuk mencari array objek untuk nilai yang cocok menggunakan operator eq, seperti:

sub find {
    my ( $self, %params ) = @_;
    my @entries = @{ $self->{_entries} };

    if ( $params{filename} ) {
        @entries = grep { $_->filename eq $params{filename} } @entries;
    }
    if ( $params{date} ) {
        @entries = grep { $_->date eq $params{date} } @entries;
    }
    if ( $params{title} ) {
        @entries = grep { $_->title eq $params{title} } @entries;
    }
    ....

Saya juga ingin dapat meneruskan variabel yang dikutip qr untuk digunakan dalam perbandingan, tetapi satu-satunya cara yang dapat saya pikirkan untuk memisahkan perbandingan adalah menggunakan blok if/else, seperti:

if (lc ref($params{whatever}) eq 'regexp') {
    #use =~
} else {
    #use eq
}

Apakah ada cara yang lebih singkat untuk melakukannya? Karena alasan di luar kendali saya, saya menggunakan Perl 5.8.8 jadi saya tidak bisa menggunakan operator pencocokan pintar.

TIA


person Sparkles    schedule 14.05.2010    source sumber


Jawaban (2)


Ini Perl, jadi tentu saja ada modul CPAN: Match::Smart. Cara kerjanya sangat mirip dengan operator pencocokan cerdas Perl 5.10, hanya saja Anda mengetik smart_match($a, $b), bukan $a ~~ $b.

Anda mungkin ingin membandingkan dengan dokumentasi Perlsyn untuk 5.10 smartmatching sebagai Match::Smart menangani beberapa situasi lainnya.

Kalau tidak, menurut saya tidak ada yang salah dengan:

sub smart_match {
    my ($target, $param) = @_;
    if (ref $param eq 'Regexp') {
        return ($target =~ qr/$param/);
    }
    else {
        return ($target eq $param);
    }
}

@entries = grep { smart_match($_->date, $params{date}) } @entries;
person rjh    schedule 14.05.2010
comment
+1 untuk memperkenalkan saya pada modul baru yang mungkin harus saya instal secara sembunyi-sembunyi di $work. - person Ether; 14.05.2010
comment
Dan sekarang saya tahu tentang Match::Smart. Ho-ho-ho. - person darch; 14.05.2010

Saya tidak tahu persis hasil akhir yang Anda inginkan, tetapi Anda dapat melakukan:

for my $field (qw(filename date title)) {
  my $p = $param($field};
  @entries = (ref($p) eq 'regexp')
    ? grep { $_->$field =~ /$p/ } @entries
    : grep { $_->$field eq $p }   @entries;
}

Alternatifnya, Anda bahkan dapat mengubah perbandingan 'eq' menjadi ekspresi reguler, misalnya:

my $entry = "string to be equal to";
my $re = qr/^\Q$entry\E/;

dan itu menyederhanakan logika dalam perulangan for.

person runrig    schedule 14.05.2010