in reply to Can this code be optimized further?

Another way.

## I'd personally use qw( ) here, but this is probalby just sample dat +a my @temp = ("a_1","b_1","a_2","a_3","a_4","b_2","a_5","b_3","a_6","b_4 +"); my( @a, @b ); my %arrays; eval qq{\$arrays{ "$_" } = \\\@$_} for qw( a b ); for( @temp ) { die "Invalid prefix on element '$_'\n" unless /^([ab])_(.*)/; push @{ $arrays{ $1 } }, $2; }

Update: Gah, left off a couple of \\ to get a reference in the eval.

Replies are listed 'Best First'.
Re^2: Can this code be optimized further?
by dragonchild (Archbishop) on Feb 10, 2005 at 14:19 UTC
    eval qq{\$arrays{ "$_" } = \\\@$_} for qw( a b ); ?!?!?

    Am I the only one that thinks unncessary evals are just ugly? While I commend you for trying to keep the surrounding code unchanged (by creating @a and @b), I think the better solution is to improve the surrounding code by making sure the appropriate data structures are used - in this case, a HoA is appropriate.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      If you can think of a better way to get a reference to an arbitrary lexical without eval sure. The original question was how to get things into arrays @a and @b; this gets things into the lexical arrays.

      Granted they may really need a HoA to begin with, but this technique (or the equivalent $arrays{ $_ } = do { no strict 'refs'; \@{ $_ } } for a package variable) sometimes is useful.

Re^2: Can this code be optimized further?
by Roy Johnson (Monsignor) on Feb 10, 2005 at 15:16 UTC
    You can use a hash to reroute things to the lexical arrays so you don't have to eval:
    my (@a, @b); my %router = (a => \@a, b => \@b); foreach my $value (@temp) { push @{$router{$1}}, $2 if $value =~ /([ab])_(.*)/; } print "@a <==> @b";

    Caution: Contents may have been coded under pressure.

      And if you had 10 arrays you'd want to keep that hash up to date? 20? 30?

      (Of course not, you'd use a HoA and not screw with this in the first place. :)

      That being said, in this specific case of just a and b I'd personally have probably used something like BrowserUK's @{ $1 eq 'a' ? \@a : \@b} below; but the eval's more flexible if you have a large number of destinations (then again with a large number of destinations you'd probably want an HoA). Of course at the moment I'd be more likely to just use Enumerable#partition and be done with it, but that's another language all together.

        And if you had 10 arrays you'd want to keep that hash up to date? 20? 30?
        The effort is linear with declaring them in the first place: one entry in the hash for each new array.

        And if your names are simply consecutive letters, the additional effort is constant: just change the ending character in the slice below.

        my @temp=qw(a_1 b_1 a_2 a_3 a_4 e_2 a_5 b_3 a_6 b_4); my %router; @router{'a'..'e'} = \(my (@a, @b, @c, @d, @e)); my $keys = join '', keys %router; foreach my $value (@temp) { push @{$router{$1}}, $2 if $value =~ /([$keys])_(.*)/; } print "@a <==> @b, @e\n";

        Caution: Contents may have been coded under pressure.