简体   繁体   English

如何比较压缩数组

[英]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? 如果打包数组中的前n个元素相同,是否有任何快速的比较方法? or to do the opposite - compare if the last m elements are different? 或做相反的事情-比较最后m个元素是否不同?

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. 有一个明显的解决方案,就是解压缩,并使用smartmatch运算符(~~),但我正在寻找直接在打包阵列上运行的东西。

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. 注意:这取决于您使用单字节字符编码的Perl安装。 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. 但这取决于您在做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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