2012-07-20 46 views
2

我有一個製表符分隔的文件(inpFile.txt)作爲閱讀Perl中的製表符分隔的文件轉換成散列和搜索

field1 field2 
aaa1 aaa2 
aaa1 bbb2 
aaa1 ccc2 
ccc1 ddd2 
eee2 aaa2 

我想讀它,並將其存儲到哈希(hashname)

一旦我的哈希準備就緒,我想搜索是否找到($ key,$ value)對。例如,如果找到(eee2,aaa2)?

我是Perl的入門者,但我知道它可以在Perl中高效地完成並且很容易。

我寫了下面的代碼。你能否進一步擴展它?

感謝

#!/usr/local/bin/perl 

open (LIST1, "/inpFile.txt") || die "File not found\n"; 
    while (<LIST1>) { 
      ($tmpvar1, $tmpvar2) = split(/\t/, $_); 
      $hashname{$tmpvar1} = $tmpvar2; 
    } 
close(LIST1); 
+0

謝謝,您問題中的代碼片段實際上是我的解決方案! – 2015-07-14 00:45:55

回答

0

輸入文件將導致只有三個元素的哈希,因爲鍵重複。在現實生活中,你有但是對付那種情況,在這種情況下,我改變你的輸入文件:

aaa1 aaa2 
bbb1 bbb2 
ccc1 ccc2 
ccc1 ddd2 
eee2 aaa2 

下面是一些增強功能代碼:

#!/usr/local/bin/perl 

#always use strict and warnings 
use strict; 
use warnings; 
use Data::Dumper; 

hash_test(); 
#Try to put your code in separate subs if possible 
sub hash_test { 
    my %hashname =(); 
    read_into_hash(\%hashname); 
    print Dumper(\%hashname); # Test your hash 
    search_hash(\%hashname, "eee2", "aaa2"); 
} 

sub read_into_hash { 

    #Always declare variables 
    my $list1; 
    my $tmpvar1; 
    my $tmpvar2; 
    my $hash_ref = shift; 
    my $lineno = 0; 
    open($list1, "<", "/inpFile.txt") or die "File not found\n"; 
    while (<$list1>) { 
     $lineno++; 
     chomp; #delete new line character 
     ($tmpvar1, $tmpvar2) = split(/\t/, $_); 
     if (defined $hash_ref->{$tmpvar1}) 
     { 
     # adding lineno from file to avoid overwriting. I use '~' just in case 
     # if your keys could include such character, use something else 
     $tmpvar1 .= "~" . $lineno; 
     } 
     $hash_ref->{$tmpvar1} = $tmpvar2; 

    } 

    close($list1); 
} 

sub search_hash { 
    my $hash_ref = shift; 
    my $key  = shift; 
    my $value = shift; 

    if (defined $hash_ref->{$key} && $hash_ref->{$key} =~ /^$value(\~\d+)*$/) 
    { 
      print "Found.\n"; 
     } 
} 
+0

我的數據有一個與多個值關聯的密鑰。 Ca代碼處理這種情況?在我的例子中,aaa1與aaa2,bbb2和ccc2都有關聯。這可能爲同一個鍵有不同的值。或者還有其他方法可以有效地做到這一點。我的文件比演出多。 – learner 2012-07-20 03:54:04

+0

更改了代碼以處理密鑰重複問題。搜索子也被改變。 – Hameed 2012-07-20 03:57:13

+0

另請注意,我使用'print Dumper($ hashname)'來測試散列元素的原因。如果你處理這麼大的文件,就把它拿出來。 – Hameed 2012-07-20 04:03:02

0

首先,當你遇到Perl,請使用pragma use strict;

我注意到你的文件處理我們的文件中包含

aaa1 aaa2 
aaa1 bbb2 

,哈希將存儲只需一鍵'aaa1' => 'bbb2',因爲Perl有哈希唯一鍵。

use strict; 

open my $fh, '<', '/input_file.txt' 
    or die "Cant open file $!"; 

LINE: 
while (my $line = <$fh>) { 
    my ($key, $value) = split /\t/, $line; 
    next LINE if not $key; 

    $hash{$key} = $value; 
} 

my $search_key = 'eee2'; 
my $search_value = 'aaa2'; 

if ($hash{$search_key} eq $search_value) { 

    print "Found key: $search_key and value: $search_value in hash /n"; 
} 

close $fh; 
+0

其實我的數據與我提到的形式相同。這可能爲同一個鍵有不同的值。或者還有其他方法可以有效地做到這一點。我的文件比演出多。 – learner 2012-07-20 03:51:21

+0

然後,您必須添加另一個級別來對相同的密鑰進行散列或添加前綴/後綴。 – Hameed 2012-07-20 03:54:10

1

首先,我理解你的問題具體到對愚弄鍵/值對。這有些尷尬 - 正常的問題只是測試密鑰,但我們可以通過將密鑰和值都輸入到生成新密鑰的函數來完成密鑰值。

如果您只是使用製表符分隔的CSV,請使用Text::CSV並放心,它是正確的,並且涵蓋了最複雜的情​​況!安裝Text::CSV_XS也使它非常快。

use strict; 
use warnings; 
use Data::Dumper; 
use Text::CSV; 
use IO::Handle; 

my $csv = Text::CSV->new({sep_char=>"\t"}); 
my $fh = IO::Handle->new_from_fd(*DATA, 'r'); 

while (not $fh->eof) { 
    my $row = $csv->getline($fh); 
    warn Dumper $row; 
} 

__DATA__ 
aa1 aaa2 
aaa1 bbb2 
aaa1 ccc2 
ccc1 ddd2 
eee2 aaa2 

當你明白了之後,其餘練習也很簡單。我使用了一個非常簡單的算法,它將key和value連接起來,並且通過它來索引hash。這消除了碰撞時的狡猾嘗試,但可能不是您的任務所必需的。隨意問的問題。

use feature ':5.10'; 
use strict; 
use warnings; 
use Data::Dumper; 
use Text::CSV; 
use IO::Handle; 
use Digest::SHA qw(sha1_hex); 

my $csv = Text::CSV->new({sep_char=>"\t"}); 
my $fh = IO::Handle->new_from_fd(*DATA, 'r'); 

my (%kv, %sha1_kv); 
while (not $fh->eof) { 
    my $row = $csv->getline($fh); 
    my ($k, $v) = @$row; 

    my $sha1 = sha1_hex($k) . sha1_hex($v); 

    if (exists $sha1_kv{ $sha1 }) { 
    say "We have a hit (key/value dupe) for $sha1 [key: $k]"; 
    } 
    else { 
    $kv{ $k } = $v; 
    $sha1_kv{ $sha1 } = $v; 
    } 

    warn Dumper $row; 
} 

__DATA__ 
aa1 aaa2 
aa1 aaa2 
aaa1 bbb2 
aaa1 ccc2 
ccc1 ddd2 
eee2 aaa2 
2

由於您的數據包含有多個值的鍵,並假設實際上在你的數據文件的情況下,你可以創建數組(HOA),其中一個關鍵是與陣列相關聯的哈希值:

use Modern::Perl; 

my %hashname; 

while (<DATA>) { 
    my ($key, $value) = split; 
    push @{ $hashname{$key} }, $value; 
} 

my $searchKey = 'aaa1'; 
my $searchVal = 'ccc2'; 

if (defined $hashname{$searchKey} 
    and $searchVal ~~ @{ $hashname{$searchKey} }) 
{ 
    say "key: $searchKey with val: $searchVal found."; 
} 
else { 
    say "key: $searchKey with val: $searchVal not found."; 
} 

__DATA__ 
aaa1 aaa2 
aaa1 bbb2 
aaa1 ccc2 
ccc1 ddd2 
eee2 aaa2 

通過首先查看是否存在關鍵字,然後使用智能匹配運算符來查看與該關鍵字相關聯的數組中是否存在該值,從而搜索「鍵/值」對。

輸出:

key: aaa1 with val: ccc2 found. 

希望這有助於!

相關問題