简体   繁体   中英

how to compare packed arrays

I have a set of arrays that are packed like this:

sub pack_key {
     return pack 'N' . ('w/a*' x @_), scalar(@_), @_;
}

because I use them as multi-value-keys in a hash (ie: the keys to the hash are arrays).

Is there any fast way to compare if the first n-elements in the packed array are the same? or to do the opposite - compare if the last m elements are different?

There is an obvious solution, which is unpacking, and using the smartmatch operator (~~), but I am looking for something operating directly on the packed arrays.

Thanks.

Because you have packed arbitrary-length data with the lengths embedded, the answer is no there is no fast way to compare two strings. You necessarily have to go through the string one component at a time.

Here is a working solution.

Caveat: this depends on your installation of Perl using a single-byte character encoding. This is most often true, but if it is not, look into Encode to make sure these strings are treated as bytes.

use strict;
use warnings;

my @arr1 = (1,2,3,4,5);
my @arr2 = (1,2,3,4,8);

sub pack_key {
     return pack 'N' . ('w/a*' x @_), scalar(@_), @_;
}

sub n_elements_equal {
    my ($compare_length,$k1,$k2) = @_;
    my $length1 = unpack('N',$k1);
    my $length2 = unpack('N',$k2);
    if ($length1<$compare_length or $length2<$compare_length) { return 0; }

    my $curr_pos = 4;
    my $curr_element = 1;

    while ($curr_element++ <= $compare_length)
    {
        my $el1 = unpack('w/a*',substr($k1,$curr_pos));
        my $el2 = unpack('w/a*',substr($k2,$curr_pos));
        if ($el1 ne $el2) { return 0; }
    $curr_pos += (unpack('w',substr($k1,$curr_pos)) + 1);       
    }
    return 1;
}

my $key1 = pack_key(@arr1);
my $key2 = pack_key(@arr2);

for (1..5)
{
    print "First $_ elements are " . 
        (n_elements_equal($_,$key1,$key2) ? '' : 'not ') . "equal.\n"; 
}

Is this better than just unpacking and doing a smart match? If your arrays are really long, then it would be faster, because you don't have to unpack the entire array. It only goes through the strings until it determines the matching status. If the arrays are not very long, it probably doesn't save you anything.

It might be better to solve this by changing your design. But that depends on what you are doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM