比较2个数组的交叉差异和公共值

时间:2014-03-24 23:39:37

标签: perl perl-data-structures

我想比较2个数组并想要diff,common和intersect值,但是代码下面的代码不起作用。 没有错误消息所有我可以看到数组作为值,虽然我调用$ difference [0]所以我怀疑代码是否正确。

   sub updatedevice() {
my $n = {};

my $Device_LINK = $server->object("ICF_PersistentDataSet",$devicelinks);
my $Temp_Device_LINK = $server->object("ICF_PersistentDataSet",$tempdevicelinks);

my @current_devicelist = @{ $Device_LINK->invoke("get") };
my @temp_devicelist = @{ $Temp_Device_LINK->invoke("get") };

my %temp_list;
my %current_list;

my $size = @current_devicelist;
for ($n=0; $n < $size; $n++) {
       our $device=$current_devicelist[$n][0];
        DEBUG( "DEBUG: - devicelinks  values $device  " );   --- > able to print this value of device "ABC-DCFE41->90"

my $size = @temp_devicelist;
for ($n=0; $n < $size; $n++) {
      our $tempdevicelinks=$temp_devicelist[$n][0];
DEBUG( "DEBUG: - temp plc links values $tempdevicelinks " ); --- > able to print this value of device "GHJKL-poiu->78"

my %count = ();
foreach my $device (@current_devicelist, @temp_devicelist) {
    $count{$device}++;
}
my @difference = grep { $count{$_} == 1 } keys %count;
my @intersect  = grep { $count{$_} == 2 } keys %count;
my @union      = keys %count;

DEBUG( "DEBUG: - difference links values $difference[0] " );
DEBUG( "DEBUG: - intersect links values $intersect[0] " );
DEBUG( "DEBUG: - union links values $union[0] " );

                }
        }
}

1 个答案:

答案 0 :(得分:2)

问题是您正在分配数组引用(从invoke返回到数组)。

你的“看'数组'作为一个值”的陈述是一个死的赠品,你正在操纵数组引用(而不是数组) - 打印时,它们变成这样的字符串:'ARRAY(0x349014)'

问题在于你正在获取一个数组引用(一个标量),并将它分配给一个数组 - 它会对你的值施加列表上下文,并将该标量转换为一个列表,其中唯一的元素就是标量。 因此,您只需将数组引用存储为数组的第一个也是唯一的元素,而不是存储像您预期的那样引用的值列表。


演示:

my @current_devicelist = (1,3); # Assign real arrays
my @temp_devicelist = (2,3);

my %count = ();
foreach my $device (@current_devicelist, @temp_devicelist) {
    $count{$device}++;
}

my @difference = grep { $count{$_} == 1 } keys %count;
my @intersect  = grep { $count{$_} == 2 } keys %count;
my @union      = keys %count;

use Data::Dumper;
print Data::Dumper->Dump([\@difference, \@intersect, \@union]
                        ,["difference","intersect","union"]);

打印:

$difference = [
                '1',
                '2'
              ];
$intersect = [
               '3'
             ];
$union = [
           '1',
           '3',
           '2'
         ];

现在,如果您通过将前两行更改为:

来模仿代码的作用
my @current_devicelist = [1,3]; # Assign reference
#    Works the same as if you said 
# my @current_devicelist = ([1,3]);
#    or
# my $current_devicelist[0] = [1,3];

my @temp_devicelist = [2,3];

...你得到:

$difference = [
                'ARRAY(0x349014)',
                'ARRAY(0x349114)'
              ];
$intersect = [];
$union = [
           'ARRAY(0x349014)',
           'ARRAY(0x349114)'
         ];

要解决您的问题,您可以执行以下四项操作之一

  1. 使用@{}取消引用

    简单地取消引用返回的数组引用
    my @current_devicelist = @{ $Device->invoke("get")      };
    my @temp_devicelist    = @{ $Temp_Device->invoke("get") };
    
  2. 更改invoke()方法 - 如果可以 - 返回数组而不是数组引用:

    # Old code: 
    # return $myArrRef;
    # New Code:
    return @$myArrRef;
    
  3. 更改invoke()方法 - 如果可以 - 根据上下文返回数组或arrayref(使用wantarray):

    # Old code: 
    # return $myArrRef;
    # New Code:
    return wantarray : @$myArrRef : $myArrRef;
    
  4. 更改代码以使用数组引用

    my $current_devicelist = $Device->invoke("get");
    my $temp_devicelist = $Temp_Device->invoke("get");
    
    my %count = ();
    foreach my $device (@$current_devicelist, @$temp_devicelist) {
        $count{$device}++;
    }