2012-03-05 35 views
5

Tôi muốn sử dụng "regex được biên dịch" (ý tôi là: biểu thức ở dạng qr/../) làm khóa cho cấu trúc băm.nhận ra "loại" của các khóa băm

Để phân biệt giữa chuỗi không đổi và các regexes khi lặp qua khóa băm, tôi đã cố gắng sử dụng ref() hoặc is_regexp(), nhưng trước đây trả về chuỗi rỗng và chuỗi sau không hoạt động. Tôi sợ tôi đang thiếu một cái gì đó cơ bản về Perl refs vs vô hướng.

Ngoài ra, giải pháp của tôi có vẻ hoạt động. Dù sao có quá xấu không? Bất kỳ đề xuất thay thế nào đều được chào đón.

Một số mã để hiểu ref() chức năng:

my $regex = qr/foo/; 
printf "ref(\$regex): %s \n", ref($regex); 
printf "is_regexp(\$regex): %d \n", is_regexp($regex); 
# ref($regex): Regexp 
# is_regexp($regex): 1 

my $scalar = 3; 
printf "ref(\$scalar): [%s] \n", ref($scalar); 
# ref($scalar): [] 

my %my_hash = ('name', 'Becky', 'age', 23); 
for my $k (keys %my_hash) { 
    printf "%s [%s] -> %s [%s] \n", $k, ref($k), $my_hash{$k}, ref($my_hash{$k}); 
} 
# name [] -> Becky [] 
# age [] -> 23 [] 
+5

Khóa trong băm là chuỗi. 'ref' sẽ luôn trả về' undef' cho những cái đó. Nếu bạn sử dụng bất cứ thứ gì làm khóa không phải là một chuỗi, nó sẽ được chuyển thành chuỗi. – Qtax

Trả lời

7

Như Qtax lưu ý trong các ý kiến, Perl phím băm là luôn chuỗi: nếu bạn sử dụng một cái gì đó khác hơn là một chuỗi như một chìa khóa băm, nó đầu tiên chuyển đổi vào một chuỗi.

Trong bình luận khác, bạn viết:

"Tôi đọc định nghĩa truy cập từ một tập tin cấu hình, tôi muốn để có thể hỗ trợ một số cú pháp mẫu, ví dụ: McDouglas, McDonald,/Mc [A-Za Sau đó tôi đọc giá trị truy cập từ tệp văn bản và tôi cập nhật các bộ đếm có liên quan tương ứng: McDonald 23 McIntosh 11 "

Nếu tôi hiểu điều này đúng, một giải pháp đơn giản có thể là lưu trữ các regex biên dịch trong một mã băm khác, được khóa trên biểu diễn chuỗi của chúng:

my @patterns = (
    'McDouglas', 
    'McDonald', 
    'Mc[A-Za-z]*', 
); 

my %regexps = map +($_ => qr/^$_$/), @patterns; 
my %counters; 

while (<>) { 
    while (my ($pat, $re) = each %regexps) { 
     $counters{$pat}++ if /$re/; 
    } 
} 

foreach my $pat (@patterns) { 
    print "$pat: ", ($counters{$pat} || 0), "\n"; 
} 
2

Có gì không ổn với việc sử dụng Tie::RegexpHash? Nó giúp bạn khỏi phải phát minh lại bánh xe :)

use Tie::RegexpHash; 

my %hash; 

tie %hash, 'Tie::RegexpHash'; 

$hash{ qr/^5(\s+|-)?gal(\.|lons?)?/i } = '5-GAL'; 

$hash{'5 gal'};  # returns "5-GAL" 
$hash{'5GAL'};  # returns "5-GAL" 
$hash{'5 gallon'}; # also returns "5-GAL" 
+0

Trong khi gói bạn đề xuất khá thú vị, nó thực hiện điều gì đó khác với những gì tôi cần. Trong trường hợp của tôi, tôi cũng có thể lưu trữ các chuỗi đồng bằng định nghĩa các regex (nhưng tôi sẽ mất quá trình biên dịch trước regex). Một trường hợp mà trwo tiếp cận xung đột là khi người ta cần lưu trữ các regex một phần chồng lên nhau. – AndreaG

+0

@AndreaG: Vui lòng cung cấp ví dụ về ý của bạn. – Zaid

+0

Tôi đọc định nghĩa truy cập từ tệp cấu hình; Tôi muốn có thể hỗ trợ một số cú pháp mẫu, ví dụ: McDouglas, McDonald,/Mc [A-Za-z] * /. Sau đó tôi đọc các giá trị bộ đếm từ các tệp văn bản và tôi cập nhật các bộ đếm có liên quan tương ứng: McDonald 23 McIntosh 11 – AndreaG

Các vấn đề liên quan