Perl匹配变量与数组阵列

问题描述:

我正在写一个脚本,它从功率计读取数据。我已经确定了几个设备使用的瓦数,并且有一个变量可以识别设备开启时的瓦数“跳跃”。我已经声明的每个设备的瓦数为一个范围,并宣布包含所有器件阵列的阵列如下 -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

我会做这样的事情:

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

一个非常有井简单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

荡涤:

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