ค้นหาอาร์เรย์ออบเจ็กต์เพื่อจับคู่ค่าหลายค่าที่เป็นไปได้โดยใช้ตัวดำเนินการเปรียบเทียบที่แตกต่างกัน

ฉันมีฟังก์ชันในการค้นหาอาร์เรย์ของออบเจ็กต์เพื่อหาค่าที่ตรงกันโดยใช้ตัวดำเนินการ eq ดังนี้:

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;
    }
    ....

ฉันต้องการที่จะส่งผ่านตัวแปรที่ยกมา qr เพื่อใช้ในการเปรียบเทียบแทน แต่วิธีเดียวที่ฉันสามารถนึกถึงการแยกการเปรียบเทียบได้คือการใช้บล็อก if/else เช่น:

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

มีวิธีที่สั้นกว่านี้ไหม? เนื่องจากเหตุผลที่อยู่นอกเหนือการควบคุมของฉัน ฉันจึงใช้ Perl 5.8.8 ดังนั้นฉันจึงไม่สามารถใช้ตัวดำเนินการจับคู่อัจฉริยะได้

ทีไอเอ


person Sparkles    schedule 14.05.2010    source แหล่งที่มา


คำตอบ (2)


นี่คือ Perl แน่นอนว่าต้องมีโมดูล CPAN: Match::Smart มันทำงานคล้ายกับตัวดำเนินการจับคู่อัจฉริยะของ Perl 5.10 มาก เพียงคุณพิมพ์ smart_match($a, $b) แทนที่จะเป็น $a ~~ $b

คุณอาจต้องการเปรียบเทียบกับ เอกสาร Perlsyn สำหรับ 5.10 การจับคู่อัจฉริยะ เนื่องจาก Match::Smart จัดการกับสถานการณ์ได้ค่อนข้างมาก

มิฉะนั้น ฉันไม่เห็นสิ่งผิดปกติกับ:

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 สำหรับการแนะนำโมดูลใหม่ที่ฉันอาจต้องติดตั้งแบบซ่อนตัวที่ $work - person Ether; 14.05.2010
comment
และตอนนี้ฉันรู้เกี่ยวกับ Match::Smart แล้ว โฮ้โฮ้โฮ้. - person darch; 14.05.2010

ฉันไม่ทราบแน่ชัดว่าคุณต้องการให้ผลลัพธ์สุดท้ายเป็นอย่างไร แต่คุณสามารถทำได้:

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;
}

หรือคุณสามารถเปลี่ยนแม้แต่การเปรียบเทียบ 'eq' ของคุณให้เป็นนิพจน์ทั่วไปได้ เช่น:

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

และนั่นทำให้ตรรกะใน for loop ง่ายขึ้น

person runrig    schedule 14.05.2010