问题
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)
回答1:
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.
回答2:
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? e.g.:
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.
来源:https://stackoverflow.com/questions/3151415/inserting-array-references-into-perl-heap