2015-09-26 72 views
1

我正在寫一個腳本,它從功率計讀取數據。我已經確定了幾個設備使用的瓦數,並且有一個變量可以識別設備開啓時的瓦數「跳躍」。我已經聲明的每個設備的瓦數爲一個範圍,並宣佈包含所有器件陣列的陣列如下 -Perl匹配變量與數組陣列

@device1 = (30..40); 
@device2 = (50..70); 
@device3 = (100..150); 
@device_array1 = (\@device1, \@device2, \@device3); 

腳本讀取來自流量計的輸出,併產生一個$watts_jump變量。然而,我無法找到一種工作方法來匹配@device_array1及其「子」陣列的變量。

我應該做一個grep還是使用List::Utils 'first'的方法?

我已經試過以下 -

use List::Utils 'first'; 
my $device = first { /$watts_jump/ } @device_array1; 

,並作爲替代grep的字符串的方法,但沒有找到匹配,並報告了回去。如果我print "$device_array1[1][2]\n";或變化 - 它確實返回正確的值。

如果匹配,我需要什麼相匹配,而不是它的索引e.g -

$watts_jump = 55,因此$device = $device2

任何幫助或指針示例將受到歡迎。正如你可能會說這是我第一次嘗試用perl和我的第一篇文章認真做任何事情,所以要溫和。指導我的perldoc的第一個人是從我的聖誕卡片名單:-)

TIA

+0

我不確定你要找什麼信息。假設您已經確定了正確的數組,那麼您的腳本將如何處理它? – melpomene

+0

我正在記錄用於數據庫的總瓦數併爲設備提供單獨的表格。所以當我看到跳過1850瓦(水壺)時,腳本會識別跳轉並通過打開設備的次數和總持續時間更新表格。 – RoyK

+0

有興趣知道當兩個設備具有(大致)sama瓦數時如何解決問題。 – rbm

回答

2

我會做這樣的事情:

my @specs = (
    { range => [30, 40], table => "foo" }, 
    { range => [50, 70], table => "bar" }, 
    { range => [100, 150], table => "baz" }, 
); 

my $table; 
for my $spec (@specs) { 
    my ($lo, $hi) = @{$spec->{range}}; 
    if ($input >= $lo && $input <= $hi) { 
     $table = $spec->{table}; 
     last; 
    } 
} 

if (!defined $table) { 
    die "Bad input: $input"; 
} 

update_the_table($table); 

也就是說,是不是擴大前的整個範圍內,然後再測試列表成員,我只是存儲端點並檢查輸入是否在這些端點之間。

我還會在相同的數據結構中存儲要更新的表的名稱,因爲它將所有相關信息保留在相同的位置。

+0

謝謝Melpomene - 我甚至不知道我可以採取這種方法。它比'grep'角度更有效率/更好的實踐嗎? – RoyK

+1

@羅伊克我覺得更容易理解。這可能更有效,因爲它不必遍歷每個設備的整個列表。 – melpomene

+0

道歉,如果這是接受答案的錯誤方式,但只是想感謝大家的幫助。我嘗試了所有三個和所有的工作。在ikegami和rbm - 你的工作,並返回數組中的索引,但沒有關聯的值。我原來的要求可能沒有足夠清楚(或者我在回覆中遺漏了某些內容)。他們雖然工作。 @melpomene - 我的第一次嘗試時,你的確做到了我所需要的,所以非常感謝 - 我會繼續努力。 – RoyK

0

一個非常有井簡單solution

use strict; 
use warnings; 

my @device1 = (30..40); 
my @device2 = (50..70); 
my @device3 = (100..150); 
my $device_array1 = {1 => \@device1, 2 => \@device2, 3=> \@device3}; 
my $dev_count = scalar(keys %{$device_array1}); 

my $value = 65; 

for (my $i=1; $i<=$dev_count; $i++) 
{ 
    if (scalar(grep $value == $_, @{$device_array1->{$i}}) > 0) 
    { 
     print "Device $i"; 
    } 
} 
+0

在各種輸入上失敗,例如'33'或'0'。 – melpomene

+0

正則表達式更新... – rbm

+0

那時,爲什麼要使用正則表達式呢? 'grep $ _ eq $ value,...'(或者說'grep $ _ == $ value,...' - 我們正在處理數字,畢竟)。 – melpomene

1

盪滌:

my @device1 = 30..40; 
my @device2 = 50..70; 
my @device3 = 100..150; 
my @devices = (\@device1, \@device2, \@device3); 

所以你想找到@devices的索引,所以你要遍歷@devices的索引。你可以這樣做:

​​

缺少的代碼應該確定識別的設備是否匹配跳轉。要檢查的設備通過索引@devices進行標識,這意味着要比較的瓦數由$devices[$_]引用。因此,您可以檢查所識別的設備跳對照如下:(加入勢力grep成標量上下文,它返回匹配的數量,而不是比賽本身)

0+grep { $_ == $watts_jump } @{ $devices[$_] } 

總之:

my @matching_device_indexes = 
    grep { 
     0+grep { $_ == $watts_jump } @{ $devices[$_] } 
    } 0..$#devices; 

如果你總是處理範圍,它更有意義,只是指定範圍的端點。

my @device1 = (30, 40); 
my @device2 = (50, 70); 
my @device3 = (100, 150); 
my @devices = (\@device1, \@device2, \@device3); 

,該方案變得

my @matching_device_indexes = 
    grep { 
     $devices[$_][0] <= $watts_jump 
     && 
     $watts_jump <= $devices[$_][1] 
    } 0..$#devices; 
+0

太好了 - 謝謝ikegami - 今天晚些時候我會放棄它,回到你身邊。 – RoyK

+0

請注意,melpomene的解決方案假設永遠不會有一次以上的比賽,但這對我來說似乎不太可能。 – ikegami

+0

請注意,我的解決方案返回的索引是基於0的。加1使它們以1爲基礎。 – ikegami