Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

sorting an array of objects (surely it should be easy!)

by jfrm (Monk)
on Jul 03, 2007 at 13:44 UTC ( [id://624681]=perlquestion: print w/replies, xml ) Need Help??

jfrm has asked for the wisdom of the Perl Monks concerning the following question:

I hope not to trouble your meditations for more than a second as I'm sure the answer to this must be obvious to all but me. I just want to sort an array of objects.

print "££".$unsorted[0]->function."<br>"; @sorted = sort {$unsorted[$a]->function <=> $unsorted[$b]->function} @ +unsorted;

I've added a print statement which works and produces correct output so I assume I have the syntax correct for the object. So why does my sort get the error messages

Use of reference "GARD::Book=HASH(0x2b7831c)" as array index at db.pl +line 439. Can't call method "function" on unblessed reference at db.pl line 439.

please help a pitiful soul...

Replies are listed 'Best First'.
Re: sorting an array of objects (surely it should be easy!)
by Fletch (Bishop) on Jul 03, 2007 at 13:55 UTC

    Because $a and $b are assigned items from the list you're sorting, not indexen. You either want to use $a->function and $b->function, or sort a list of indexen (sort { $unsorted[$a]->function ... } 0..$#unsorted).

    Also if $unsorted[$idx]->function is expensive (or possibly changes during the course of the sort) you might want to do a schwartzian transform first and just make one set of calls.

    Update: Oop, you know if you don't know what sort passes to the sort block you probably don't know what an ST is . . .

    @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, $_- +>function ] } @unsorted;

    (Of course were this Ruby that'd just be unsorted.sort_by { |x| x.function }; how easily one can get spoiled . . . :)

Re: sorting an array of objects (surely it should be easy!)
by naikonta (Curate) on Jul 03, 2007 at 14:58 UTC
    Whenever you get errors or warnings, I suggest you look up the perldiag manual page to see more verbose explanation. Or, you can put the use diagnostics; line near the top of your program. This way, you let Perl explains more detail about what's wrong or what might be wrong in your program. The first is really a warning message instead of an error (indicated by "(W)", while the second is a fatal error.
    Use of reference "%s" as array index (W misc) You tried to use a reference as an array index; this probab +ly isn't what you mean, because references in numerical context tend to + be huge numbers, and so usually indicates programmer error. If you really do mean it, explicitly numify your reference, like so: $array[0+$ref]. This warning is not given for overloaded objects, either, because you can overload the numifi- cation and stringificat +ion operators and then you assumedly know what you are doing. Can't call method "%s" on unblessed reference (F) A method call must know in what package it's supposed to run. I +t ordinarily finds this out from the object reference you supply, but +you didn't supply an object reference in this case. A reference isn't a +n object reference until it has been blessed. See per- lobj.
    The @unsorted array contains list of objects of GARD::Book class, when you pass it to the sort function, the $a and $b variables contain references to the correspondent elements in that array. So you simply say $a->function instead of $unsorted[$a]->function in the sort block.

    Saying $a->function in the sort block is the same with $unsorted[SOME_INDEX]->function outside the block. When you say $unsorted[$a]->function in the sort block the following (more or less) happens:

    • $a becomes a reference of one of @unsorted element, which is an object of GARD::Book
    • Now you're using that reference (stringified as GARD::Book=HASH(0x2b7831c)) as array index, but, usually, this is not something you want, hence the warning. Imagine that you're actually doing $unsorted["GARD::Book=HASH(0x2b7831c)"]->function instead of $unsorted[0]->function.
    • The $unsorted[$a] is evaluted to some reference and used to call a method. But we need more than a mere reference to call a method, we need a blessed reference, and that's what object is all about in Perl (see the first few lines in the perlobj). That's what triggered the fatal error: unblessed reference was used to call a method.

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://624681]
Approved by naikonta
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-19 23:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found