Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

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

by jfrm (Monk)
on Jul 03, 2007 at 13:44 UTC ( #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 +line 439. Can't call method "function" on unblessed reference at 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?

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

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2022-05-19 02:37 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (71 votes). Check out past polls.