Question

I want to compare 2 arrays and want diff , common and intersect values but below code is not working. No error message all I can see Array as an value although I am calling $difference[0] so I doubt if the code is correct.

   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] " );

                }
        }
}
Was it helpful?

Solution

The problem is that you're assigning array reference (returned from invoke to an array).

Your statement of "see 'array' as a value" is a dead giveaway that you're manipulating array references (instead of arrays) - when printed, they turn into strings like this: 'ARRAY(0x349014)'

The problem is that you're taking an array reference (a scalar), and assigning it to an array - which imposes list context on your value, and turns that scalar into a list with its only element being that scalar. Thus you simply store the array reference as the first and only element of the array - instead of storing the list of values that's being referenced like you intended.


To demonstrate:

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"]);

This prints:

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

Now, if you mimique what your code was doing instead by changing the first 2 lines to:

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];

... you get:

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

To fix your problem, you can do one of 4 things:

  1. Simply dereference your returned array references, using @{} dereference:

    my @current_devicelist = @{ $Device->invoke("get")      };
    my @temp_devicelist    = @{ $Temp_Device->invoke("get") };
    
  2. Change invoke() method - if you can - to return an array instead of array reference:

    # Old code: 
    # return $myArrRef;
    # New Code:
    return @$myArrRef;
    
  3. Change invoke() method - if you can - to return an array OR an arrayref based on context (using wantarray):

    # Old code: 
    # return $myArrRef;
    # New Code:
    return wantarray : @$myArrRef : $myArrRef;
    
  4. Change your code to use array references

    my $current_devicelist = $Device->invoke("get");
    my $temp_devicelist = $Temp_Device->invoke("get");
    
    my %count = ();
    foreach my $device (@$current_devicelist, @$temp_devicelist) {
        $count{$device}++;
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top