2009-11-18 54 views
2

如何刪除我不感興趣的數組項目?如果我將他們留在—我的記憶會溢出不必要的項目。如何根據年齡刪除Perl哈希或數組項目?

我需要在Perl中實現一個任務。一個文件正在不斷地充滿包含的信息:

"IP - URL" 

我需要不斷地讀取這個文件和衡量,如果有不止,覺得五,同IP - URL雙,比方說,五週秒鐘的時間間隔。

如果我每五秒從上一個位置讀取文件並計算重複次數,那麼當五秒鐘內有八個相同的行對時,但在第一次讀取時,有四個相同行,而另外四個是第二個五秒鐘後讀取。因此我需要檢查最後五個重複行之間的間隔。

我可以:

$pairs[$ip_url_line] = ['time-stamp',....,'time-stamp-N'] 

然後得到最後五數組項爲這個哈希鍵和計算時移。如果超過5秒—做些什麼。

當然,我可以通過所有的哈希元素,並在循環中的所有陣列項目運行,並檢查它是否是舊的,然後5秒,但它太資源昂貴。

回答

5
  1. 存儲每個IP地址的時間戳秩序。無論如何,你可能會這麼做。
  2. 每當你得到一個日誌行並添加一個新條目時,在你檢查有多少條目之前,刪除所有舊條目。您可以使用grep輕鬆完成。
  3. 定期(每分鐘一次?)從哈希中刪除具有超過5分鐘前​​的最後一個(最新)時間戳的IP地址,因爲這意味着全部條目超過5分鐘,並且該地址hasn有一段時間沒有看到。

這很簡單,很容易證明是正確的,它試圖避免一次做太多的工作,並且它可以防止你的桌子變得不合理地變大。步驟3以1分鐘的時間間隔,無法進入超過11分鐘。 (如果在00:00:00添加了1.2.3.4的第一個條目,則可以添加最近的一個條目而不移動第一個條目爲00:04:59。最後一個步驟3的掃描可以運行而不刪除整個陣列將是00:09:58;假設最壞的情況下,下一次掃描將在00:10:58)。如果你可以保留11分鐘的數據在內存中,你是金。

+1

我的同事討論的想法後,我們已經找到更加有效的方式:1。 每次進入被添加到陣列 - 只保留最後10級陣列的項目。 2.刪除超過5秒的項目。 3.如果有超過10個項目 - 做一些動作 ++++你的想法 一分鐘循環通過所有哈希項目。如果最後一個數組項時間戳超過5秒 - 刪除散列元素。 解決! 謝謝! 有時候告訴某人你的想法和實施方式已經足夠了,並且你會對你的問題有一個答案)) – 2009-11-18 11:48:11

+1

你可以告訴我在閱讀你的問題時, - 顯然我在腦海中寫下了「5分鐘」。 :) – hobbs 2009-11-18 12:11:35

4
#!/usr/bin/perl 

use strict; use warnings; 

my @ts; 

for (1 .. 10) { 
    push @ts, time; 
    sleep rand 3; 
} 

my $now = time; 
@ts = grep { $now - $_ <= 5 } @ts; 

print $_, "\n" for @ts; 
1

這聽起來像你想要某種最近最少使用(LRU)緩存。雖然我不經常推薦它,但我認爲這是一個捆綁散列或數組的工作。當你這樣做時,你會清除舊的元素。這將複雜性從高級元素中解放出來,並將其隱藏在普通數組或哈希訪問之後。以Tie::Cache爲例。

或者,你可以保持某種形式的FIFO,其中從陣列的一端添加新元素,然後檢查另一端的項目刪除。