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

I have a hash of $var => $cnt. I want to flatten this to an array of $var's in which each $var occurs $cnt number of times. I implemented this via map() and a subroutine that expands a $var into an array occuring $cnt number of times as follows:
my @flat = map { exp_arr($_, $hash{$_}) } keys %hash; sub exp_arr { my $var = shift; my $cnt = shift; my @arr; for ( my $i = 0; $i < $cnt; $i++ ) { push @arr, $var; } return @arr; }
However, this looks like a lot of code to do something this trivial. There must be some inherent Perl feature that I'm missing that accomplishes this. Probably something akin to the x operator which repeats a scalar X number of times, or array slicing, or something to that effect.

Replies are listed 'Best First'.
Re: Pushing Element Multiple Times to Array
by CountZero (Bishop) on Feb 13, 2011 at 09:53 UTC
    use Modern::Perl; my %hash = ( yes => 4, no => 3, maybe => 5, perhaps => 2, ); my @flatlist = map { ($_) x $hash{$_}} keys %hash; say "@flatlist";
    Output: yes yes yes yes perhaps perhaps maybe maybe maybe maybe maybe no no no

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Pushing Element Multiple Times to Array
by perlchanter (Novice) on Feb 13, 2011 at 09:22 UTC

    Were you meaning something like this?

    my @arr; map { push( @arr, ( ( "$_" ) x $hash{$_} ) ) } keys %hash;

Re: Pushing Element Multiple Times to Array
by Anonymous Monk on Feb 13, 2011 at 09:13 UTC
    push @arry, ( $var ) x $cnt;
    or longwinded
    push @arry, $var for 0 .. $cnt; push @arry, map { $var } 0 .. $cnt;
      "Off by one" error in 0 .. $cnt! It should be 1 .. $cnt.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Pushing Element Multiple Times to Array
by Anonyrnous Monk (Hermit) on Feb 13, 2011 at 09:15 UTC
    while (my ($var, $cnt) = each %hash) { push @flat, ($var) x $cnt; }

    Unlike with the respective map solution, this allows you to use self-documenting variable names, and it also scales better performance-wise (both memory and execution time).  (Some people still prefer to use map — presumably because it allows them to show they've grasped basic functional programming concepts (or so, I guess).)

Re: Pushing Element Multiple Times to Array
by atancasis (Sexton) on Feb 13, 2011 at 09:54 UTC
    Thank you! I knew that I was missing something. Thanks everyone for pointing out that the x operator accomplishes what I want when used in an array context.