简体   繁体   中英

Inserting Array References into Perl Heap

I am inserting 2-dimensional array references into my heap in Perl. How should I define the 'elements' attribute when constructing my heap so that I can properly use my comparator function?

my $heap = Heap::Simple->new( order     => \&byNumOrStr,
                              elements  => [Array => 0]
                             );

sub byNumOrStr
{
    my ( $a, $b ) = @_;

    $b->[0] <=> $a->[0]  #0-th element is a number. 
            ||
    $a->[1] cmp $b->[1]; #1-st element is a number
}

I keep getting back this error:

Can't use string ("2.55") as an ARRAY ref while "strict refs" in use ... (This means I might actually have to compare my "number string" numerically)

Well, it's likely that either $a or $b is being passed in as a string. Try printing out this variables after the assignment.

From what I can see from the documentation, when you pass elements => [ Array => 0 ] , unless the 0th item in the array is an array then you'll only be comparing the values in the first slot of the array.

[Array => $index]
Indicates that the elements are array references, with the key at index $index. So now the element can be not just the key, but also associated data.

This means that if 2.55 is in the array like [ 2.55, ... ] then that's what's being passed in as $a or $b .

The elements entry tells H::S how you want to derive the key. For a completely generic way, it says that you can pass [Function => $code_ref_for_key] . You could make it like this:

sub first_two_slots { my $array_ref = shift; return [ @$array_ref[0,1] ]; }

And then with the order as specified, it would pass that array into your order and specify

my $heap = Heap::Simple->new( order     => \&byNumOrStr,
                              elements  => [Function => \&first_two_slots]
                             );

Original comment left in place: (It's not relevant to how Heap::Simple calls order).

if byNumOrStr is called from sort DON'T assign $a and $b in it. Those values are set by sort . If there is something coming in @_ it's probably not what you want.

Sorting a two-dimensional array doesn't really make sense -- when you sort something, there is a defined order. Having two sort criteria doesn't make it a two-dimensional list... do you mean that you have data that are a list of two elements? eg:

my $element = [ '0', 'string' ];

I think Example 1 in the documentation ("where key and value are kept separate") applies here -- you want to sort the references, not the values themselves. So try declaring with elements => "Any" , and then adjust your sort method to match:

(I was wrong.. it looks like elements => [Array => 0] is correct, since these are just plain old arrayrefs being sorted.

my $heap = Heap::Simple->new( order     => \&byNumOrStr,
                              elements  => [Array => 0],
                             );

sub byNumOrStr
{
    my ( $val1, $val2 ) = @_;

    my $result = 
        $val1->[0] <=> $val2->[0]  # the 0th element is a number
                    ||
        $val1->[1] cmp $val2->[1]; # the 1st element is a string

    # The docs say "this should return a true value if $key1 is smaller than $key2 and a false value otherwise."
    return $result == -1;
}

PS. As discussed in Secondary Order in Heap::Simple , the comparison function in Heap::Simple does not want a return value of -1, 0, or 1, but rather true or false. You need to convert the comparison result before returning from the function.

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