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

From time to time one might need to set multiple elements in an array to a single value, such as:
my @array; my ($i,$j); for ($i=0; $i<4; $i++) { $array[$i]= 1000; } for ($j=4; $j<10; $j++) { $array[$j]= 50; }
Is there anyway to initialize/update array elements using 'slicing' instead of looping? E.g.
my @array; ### wrong syntax $array[0..3] = 1000; ### wrong syntax $array[4..9] = 50;
If there is such a way, what is the syntax?

And comparing to looping, which is a faster way to mass update array elements?

Thank you.

Replies are listed 'Best First'.
Re: Array How to/Performance: mass initialization or update using array slice
by BrowserUk (Patriarch) on Jun 21, 2003 at 08:44 UTC

    So close:)

    @array[0..3] = (1000) x 4;

    A little explanation:

    Slices (whether array or hash) always start with the '@' sigil. See perldata search for "Slices".

    x is the perl repetition operator. See perlop Search for "Multiplicative Operators".


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Re: Array How to/Performance: mass initialization or update using array slice
by Anonymous Monk on Jun 21, 2003 at 08:49 UTC
    Wow that's a light speed respond. Thank you!

    Oh yeah, it should be @array[0..3] but not $array[0..3] since end result is a list.

    However, which way has a faster run time, slicing or looping? Thank you.

      Off the top of my head I seem to recall that the slice operation is quicker than using a loop as most of the work is being done in C rather transitioning between C and perl as with a loop. However, you would probably need to be setting a few hundred elements of the array at a time, and/or doing this very often before you would notice the difference in runtime of your script.

      That said, the slice method is very clean syntactically, so there is no reason not to use it, and any performance benefit never hurts, and is a nice bonus.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


        #!/usr/bin/perl -w -- use strict; use Benchmark 'cmpthese'; cmpthese(-3,{ 'perloop' => sub { my @array; for(0..49) { $array[$_]=50; } return(); }, 'c-loop' => sub { my @array; for(my $i=0; $i<50; $i++) { $array[$i]=50; } return(); }, 'rangeslice' => sub { my @array; @array[0..49] = (50) x 50; return(); }, 'literalslice' => sub { my @array; @array[ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, 38,39,40,41,42,43,44,45,46,47,48,49 ] = ( 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50 ); return(); }, 'literalassign' => sub { my @array = ( 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50 ); return(); }, 'repeatassign' => sub { my @array = (50) x 50; return(); }, }); __END__ Benchmark: running c-loop, literalassign, literalslice, perloop, range +slice, repeatassign, each for at least 3 CPU seconds... c-loop: 3 wallclock secs ( 3.39 usr + 0.00 sys = 3.39 CPU) @ + 31973.75/s (n=108391) literalassign: 4 wallclock secs ( 3.09 usr + 0.00 sys = 3.09 CPU) @ + 122232.14/s (n=378064) literalslice: 4 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ + 92383.00/s (n=277149) perloop: 4 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ + 40371.54/s (n=121155) rangeslice: 3 wallclock secs ( 3.02 usr + 0.00 sys = 3.02 CPU) @ + 65742.71/s (n=198280) repeatassign: 4 wallclock secs ( 3.19 usr + 0.00 sys = 3.19 CPU) @ + 129130.18/s (n=411667) Rate c-loop perloop rangeslice literalslice literala +ssign repeatassign c-loop 31974/s -- -21% -51% -65% + -74% -75% perloop 40372/s 26% -- -39% -56% + -67% -69% rangeslice 65743/s 106% 63% -- -29% + -46% -49% literalslice 92383/s 189% 129% 41% -- + -24% -28% literalassign 122232/s 282% 203% 86% 32% + -- -5% repeatassign 129130/s 304% 220% 96% 40% + 6% --
        Oh I see.

        I guess I'll do a test and see how big the difference would be.

        Thank you again.
Re: Array How to/Performance: mass initialization or update using array slice
by Anonymous Monk on Jun 21, 2003 at 08:55 UTC
    Thank you for the extra explanation.

    Still, which one is faster, looping or slicing for mass update? Thank you.
      Do you have a performance problem confirmed in a profiler at that point in your program? No? Then it doesn't matter.

      Makeshifts last the longest.

        But... isn't it good to know the fastest way for future reference? And... isn't tuning a good pedalogical tool for understanding Perl internals?

        -Tats
Re: Array How to/Performance: mass initialization or update using array slice
by Anonymous Monk on Jun 22, 2003 at 02:56 UTC
    Thank you everyone for your help. Now I have learned a thing or two about benchmarking and slicing in Perl. Thank you.