2017-03-22 166 views
0

程序將非常大的字典式TXT文件讀入哈希。有時,有一個小寫版本的密鑰是可取的。下面我的解決方案是笨拙的,因爲它會搜索兩次,即使我們已經知道lc版本存在:哈希:測試密鑰

if (exists $hash{ lc $key }) { 
    $key = lc $key; 
} 
if (exists $hash{ $key }) { 
    # lot of code involving $key 
} 
else { 
    # the key doesn't exist, other code 
} 

有沒有一種方法,以避免出現兩個exists測試?如果lc $key存在,我想對第二個if做相同的代碼,但是我需要知道使用哪個版本lc或者不是$key。我希望將它凝聚成一對if-else對。

瞭解有效密鑰的情況對程序的其他部分很重要,因爲它用於查找另一個散列中的信息。

+0

這是否意味着您可以在同一個散列中同時擁有'foo'和'FOO'作爲鍵? – ThisSuitIsBlackNot

+0

是的。這是名字和單詞的散列。有些名字也是單詞。所以如果用戶提供「約翰」和「約翰」,那麼「約翰」就是我所追求的。然後,我使用「john」來搜索另一個散列的值,並提供與「john」相關但不包含「John」的那個散列的所有關鍵字。 –

+0

當您將這些鍵讀入搜索索引時,將這些鍵標準化,但這可能不值得。與較大的費用相比,兩個哈希查找並不昂貴。或者把文件放入SQLite並使用SQL(這將解決很多問題)。 – Schwern

回答

3
if (my ($real_key) = grep { exists($hash{$_}) } lc($key), $key) { 
    ... 
} else { 
    ... 
} 

my $real_key = 
    exists($hash{ lc($key) }) ? lc($key) 
    : exists($hash{ $key  }) ? $key 
    : undef; 

if (defined($real_key)) { 
    ... 
} else { 
    ... 
} 

當然,它仍然搜索兩次,還等什麼?你可以使用List :: Utils的first,但我認爲用子調用替換哈希查找實際上可能會減慢代碼的速度!

+1

在散列上使用'exists'兩次而不是性能問題?我正在尋找替代品,因爲散列有超過250,000個條目。 –

+1

@Erik Olson,散列查找是O(1),這意味着它們不受散列大小的影響。 – ikegami

+0

兩個哈希查找可能更容易閱讀,而且處理速度比一個棘手的單線索要快。只是爲了我自己的教化,在你的例子中'grep'在一個步驟中是否返回小寫'$ key',如果有效的話,還是每次都檢查普通的'$ key'?謝謝! –

0

您可以使用List::Utilfirst。它將返回代碼塊結果爲真值的第一個列表元素,如果該塊永不返回true,則返回undef

use List::Util qw(first); 

$key = first { exists($hash{$_}) } lc($key), $key; 

if (defined($key)) { 
    # ... 
} 
0

你也可以這樣做:

$key = do { my $temp = lc $key; exists $hash{$temp} ? $temp 
     : (exists $hash{$key} ? $key : undef) }; 

if (defined $key) { 
    # lot of code involving $key 
} 
else { 
    # the key doesn't exist, other code 
}