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

Brethern,

I have a hash, %unk. Its values are tab-delimited lists of alphanumeric IDs. I want to print out the hash, with entries sorted in descending order by how many IDs they have. I use the Schwartzian transform . It works well but I've had to use a hack:

use vars qw(%unk, @foo); my(@ulist) = map{ # Sort descending $_->[1] } sort{ $b->[0] <=> $a->[0] } map{ [scalar(@foo=split(/\t/, $unk{$_})), $_ ] } keys %unk;
The hack is @foo; it's an unused variable. But if I drop it:
[scalar(split(/\t/, $unk{$_})), $_ ]
I get the warning
Use of implicit split to @_ is deprecated at extractions line 393.
Is there a better workaround than what I'm doing?

throop

Replies are listed 'Best First'.
Re: Bogus variable to avoid 'split' warning
by merlyn (Sage) on Feb 16, 2007 at 19:45 UTC
    Use tr/\t// to count tabs, instead of split. Then you won't have the warning.
    update: yes, this miscounts trailing tabs. But the original spec was a bit fuzzy. {grin}

      ...and don't forget that you're counting something slightly different.

      tabcount( "a\tb\tc", 'three fields' ); tabcount( "a\tb\t", 'two fields, trailing tab' ); tabcount( "\tb\tc", 'two fields, leading tab' ); sub tabcount { my ( $tabby, $descr ) = @_; print "*** $descr ***\n"; printf "scalar split %d\n", scalar split( /\t/, $tabby); printf "tr/\\t/: %d\n", $tabby =~ tr/\t//; }

      Output:

      *** three fields *** scalar split 3 tr/\t/: 2 *** two fields, trailing tab *** scalar split 2 tr/\t/: 2 *** two fields, leading tab *** scalar split 3 tr/\t/: 2
Re: Bogus variable to avoid 'split' warning
by Tanktalus (Canon) on Feb 16, 2007 at 20:05 UTC

    Two possibilities strike me. First, just replace @foo with ():

    [scalar(()=split(/\t/, $unk{$_})), $_ ]
    That's the =()= operator there, just missing the left equals. Should do what you want the way you're doing it.

    Second, any time I see "xxx-delimited", I think "DBD::CSV". I don't know - I just find it more natural to phrase my querying code in a query language. Which, of course, makes it a bit more trivial to move data around without affecting your logic... into a comma-separated file, or into a SQLite database, or mySQL, or Oracle or DB2 or ... maybe it's just me, but I like that flexibility.

Re: Bogus variable to avoid 'split' warning
by Cristoforo (Curate) on Feb 16, 2007 at 20:55 UTC
    @ulist = sort {$b =~ tr/\t// <=> $a =~ tr/\t//} keys %unk;
    This is an alternative way to sort it.

    Chris

Re: Bogus variable to avoid 'split' warning
by Moron (Curate) on Feb 19, 2007 at 12:27 UTC
    Albeit the Schwarzian transform is a clever solution, user-programmers can suffer from the rule that ready-made solutions are apt to break at the slightest deviation from the requirement they originally met. I am not saying this is a particularly flagrant case, but as a rule, instead of hacking away at a not-quite-fitting algorithm, it might be an idea to try to construct the solution more directly from the actual requirement, e.g.:
    my %count; my @ulist = sort { ($count{ $b } ||= TabCount( $b ) ) <=> ($count{ $a } ||= TabCount( $a ) ) } values %unk; sub TabCount { $_ = shift; s/\s+$//; my @split = split /\t/; return $#split; }

    -M

    Free your mind