So I was on #cgiapp (irc.perl.org) and Cees Hek taught me a few things, one involving lists, arrays and scalars.
Have you ever tried this?
@a=('one','two','three'); $b = @a; print $b;
So what's the output? '3' ... I knew that and my world was safe & sheltered. Then Cees threw this one at me:
$b = ('one','two','three');print $b;
What's that output? '3'? ... Nope, it's 'three', the last element of the list.
insert sound of head exploding
Before moving on, I think this is a good example of how such a truth of life can really alter your worldview. Not just in Perl, but when you learn something new like that, it really breaks your grip on "reality" and takes a moment (or two) to readjust and get a new grip. I encourage a good shake-up every once in a while.
Ok, so then I was head-coding while playing with Meredith (she's so cute), getting around a CSV file that I will need to import into a database and it has rows with ID #'s and then a column in a row for other ID #'s that are the same 'entity'. So I plan on consolidating them into my shiny new relational db. So I'll need something to determine if the ID # is the minimal # of the set - if so, it's a new 'entity' record. Otherwise, associate the new record w/ the minimal number.
So I'll have the ID # and a list of other ID #'s and I need to know if it's the smallest.
So then I said to myself ... what if I used that concept that Cees taught me w/ a reverse sort? Like:
if ( $id_number == reverse sort @ids )
There are some context issues there that I couldn't (and still don't all that well) understand. Cees nailed it, though:
if ( $id_number == @{[reverse sort @ids]}[0..$#ids] )
Pretty cool, huh? I call it the Hek-Purdy min(). Or maybe "a Hek of a Purdy-good min() function" (helps if you say that in a Southern accent ;)).
Now this is not very readable or maintainable, so I don't plan on world-wide deployment - just my import script ... for now. ;)
Peace,
Jason
You went a very convoluted route to do this:So I'll have the ID # and a list of other ID #'s and I need to know if it's the smallest.
Learn about literal slice: (LIST)[INDICIES]. We document it in Learning Perl.if ( $id_number == (sort @ids)[0] )
Re:Why so convoluted? Use a literal slice!
Purdy on 2005-09-07T13:56:44
*grin* - yeah, I know. I should have put a * next to "good" - I'm not endorsing that as THE way: TIMTOWTDI and all that. And your approach is definitely cleaner... I was just thinking about how to incorporate what I learned about scalarizing a list.
Peace,
Jason
So I'll have the ID # and a list of other ID #'s and I need to know if it's the smallest.
That code is very confusing. Sorta like taking a flight from NY to LA by via Johannesburg and Perth. Why not just grab the smallest element of the list?
use List::Util qw(min);
if ( $id_number == min(@ids) )
If you needed to avoid List::Util for some odd reason, I don't know why you would sort a list, reverse it and take the last element (in a most convoluted fashion) when you could just:
if ( $id_number == (reverse sort @ids)[-1] )
Or even more clearly:
if ( $id_number == (sort @ids)[0] )
Re:min()
Purdy on 2005-09-07T14:04:04
*nod* - agreed. See prev. comment - I simply wanted to apply what Cees taught me about scalarizing a list.
Hmmm -- maybe this won't even see the light of day in my import script now.;)
Peace,
Jason
I thought it was common knowledge that there is no such thing as a list in scalar context.
The context issues are particularly important when you return
things. my $foo = bar();
will produce a different result with a bar
function that does return @arr;
vs one that does return ( $baz1, $baz2, $baz3 )
. This is even more insidious if you do something like return grep quux($_), @arr
.
Always mind your context.
Your particular example, btw, besides all the issues already pointed out by others, should at least be written without that anonymous array in there:
if ( $id_number == ( reverse sort @ids )[ 0.. $#ids ] ) {
#...
}
which then leads to the further simplifications ziggy pointed out.