Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Adding an new element after every 5th element in array

by dvinay (Acolyte)
on Nov 26, 2013 at 18:57 UTC ( #1064447=perlquestion: print w/replies, xml ) Need Help??

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

Hi monks,

I have an requirement where, in array has 120 elements and these are divided into sets of 3, so there are 40 sets, each containing 3 commands, now i need to insert or add an new element at multiples of 10's set (i.e after 10th set, 20th Set 30th set, 40th set....! is there any way to do it..? i tried splice function but didnt get required results.

Any help is appreciated

sample array is as given below its only having 20 sets that is totally 60 commands or elements now i need to add an new element at every 10th set element

my @array ("create", "mount", "remove","create", "mount", "remove","cr +eate", "mount", "remove","create", "mount", "remove","create", "mount +", "remove","create", "mount", "remove","create", "mount", "remove"," +create", "mount", "remove","create", "mount", "remove","create", "mou +nt", "remove","create", "mount", "remove","create", "mount", "remove" +,"create", "mount", "remove","create", "mount", "remove","create", "m +ount", "remove","create", "mount", "remove","create", "mount", "remov +e","create", "mount", "remove","create", "mount", "remove","create", +"mount", "remove");

Replies are listed 'Best First'.
Re: Adding an new element after every 5th element in array
by davido (Cardinal) on Nov 26, 2013 at 19:18 UTC

    You should show what code you used in your splice implementation, because it certainly could work, assuming you're using it right.

    If I were doing this, and memory weren't a constraint, I would make a new array, and then replace the old one with the new one once done. The reason is that every time you insert into the middle of an array, all elements that follow must be shifted to the right one step, which is relatively expensive. Here's an example of how I would do it:

    @array = do { my @array2; foreach ( @array ) { push @array2, $_; push @array2, "new_element" if $_ eq 'remove'; } @array2; };

    Or, avoiding the temporary @array2:

    @array = map { $_, ( $_ eq 'remove' ? "new element" : () ) } @array;

    For additional efficiency, you might do it this way instead:

    @array = map { $array[$_], ( ($_+1) % 3 == 0 ? "new element" : + () ) } 0 .. $#array;

    The latter avoids a full string comparison on each iteration, by keeping track of index number rather than element contents.


    Dave

      hi dave,

      Thanks for the solution, but i need one more change in requirement, instead of adding the new element after "remove", i need to add the new element say after every multiples of 10th set, i.e. 10th set, 20th set,30th set and 40th set.

      How it can be achieved...?

        in my final example it is as easy as changing the number 3 to some other interval. Take the time to understand the solutions we provide and you will understand how to modify them to your needs.


        Dave

Re: Adding an new element after every 5th element in array
by Cristoforo (Curate) on Nov 26, 2013 at 19:22 UTC
    You need to splice in elements starting from the end to the beginning. Otherwise, you will confuse splice (as new items added to the front invalidates the following indices). (What used to be say, index 4 will get moved up 1 when a new item is added in front).

    When you splice in from the end, you leave the preceding indices alone.

    for my $i (reverse 0 .. $#array) { if (($i+1) % 3 == 0) { splice @array, $i+1, 0, "new item"; } } use Data::Dumper; print Dumper \@array;
    Ah, I see davido has the better solution - more efficient.

      Thanks for the solution, but i need one more change in requirement, instead of adding the new element after "remove", i need to add the new element say after every multiples of 10 set, i.e. 10th set, 20th set,30th set and 40th set.

      totally we have 20 sets right, i need to add one new element after 10th set and other one after 20th set

      How it can be achieved...?

Re: Adding an new element after every 5th element in array
by Kenosis (Priest) on Nov 26, 2013 at 19:23 UTC

    Since the commands are in a regular pattern, you could do this:

    use strict; use warnings; use Data::Dumper; my @array = ( "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove", "create", "mount", "remove" ); my @newArray; while ( my @tmp = splice @array, 0, 3 ) { push @newArray, @tmp, 'newelement'; } print Dumper \@newArray

    Partial output:

    $VAR1 = [ 'create', 'mount', 'remove', 'newelement', 'create', 'mount', 'remove', 'newelement', 'create', 'mount', 'remove', 'newelement', ...

    Hope this helps!

Re: Adding an new element after every 5th element in array
by thezip (Vicar) on Nov 27, 2013 at 00:31 UTC

    dvinay,

    I could't help but notice that your array just screams to be an array of arrays. I say this because it regularly repeats itself every three elements. I know this wasn't your original spec, but I offer the following advice.

    If you structured your array as:

    my @array = qw/ create mount remove /; my $array = [ ['create', 'mount', 'remove'], ['create', 'mount', 'remove'], \@array, # essentially the same values \@array, ... ];

    ... then you could easily add items to the end of each of sub-array by iterating and pushing:

    #!/perl/bin/perl use strict; use warnings; use Data::Dumper; for my $subarray (@$array) { push(@$subarray, 'foo'); } print Dumper($array);
    __OUTPUT__ $VAR1 = [ [ 'create', 'mount', 'remove', 'foo' ], [ 'create', 'mount', 'remove', 'foo' ], [ 'create', 'mount', 'remove', 'foo' ], [ 'create', 'mount', 'remove', 'foo' ], ];

    What can be asserted without proof can be dismissed without proof. - Christopher Hitchens, 1949-2011
Re: Adding an new element after every 5th element in array
by boftx (Deacon) on Nov 26, 2013 at 19:54 UTC

    Here is a code snippet with an approach using splice that might get you where you want (assume proper strictures, etc.):

    my $element_size = 3; my $group_size = 10; #adjust as needed for 5th, 7th, etc. my $block_size = $element_size * $group_size; # since "elements" are v +irtual my @new; while ( @old_array ) { if ( @old_array < $block_size ) { # don't add new if old is too sm +all push(@new, @old_array); last; } push(@new, splice(@old_array,0,$block_size); # "shift" out of old push(@new,qw( create mount remove )); # new "element" added here } # UPDATE: added code to put remainder of @old_array onto @new if not # a full multiple.

    The above code assumes that you only want to add a new "element" if a full multiple of "group_size" is present.

    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
Re: Adding an new element after every 5th element in array
by hdb (Monsignor) on Nov 26, 2013 at 20:20 UTC

    I would use splice to remove a set from the beginning of the array and push it onto a new array. Repeat 10 times. push your new element onto the new array. Repeat until original array is exhausted.

    use strict; use warnings; use Data::Dumper; my @array = ("create", "mount", "remove","create", "mount", "remove"," +create", "mount", "remove","create", "mount", "remove","create", "mou +nt", "remove","create", "mount", "remove","create", "mount", "remove" +,"create", "mount", "remove","create", "mount", "remove","create", "m +ount", "remove","create", "mount", "remove","create", "mount", "remov +e","create", "mount", "remove","create", "mount", "remove","create", +"mount", "remove","create", "mount", "remove","create", "mount", "rem +ove","create", "mount", "remove","create", "mount", "remove","create" +, "mount", "remove"); my $nset = 3; my $every = 10; my $newelement = "newelement"; my @newarray; while( @array ) { for( 1..$every ) { # for 10 times push @newarray, splice @array, 0, $nset; # push a set onto new arr +ay } push @newarray, $newelement; # add the new element } print Dumper \@newarray;

      Nevermind, this is completely wrong. :(

      I think hdb's example could be simplified a bit plus avoid any old-size remainder problems like this:

      while( @array ) { push @newarray, splice @array,0,$nset; next if @newarray % ($nset * $every); # no need for a counter w +ith % op push @newarray, $newelement; # add the new element }
      It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
Re: Adding an new element after every 5th element in array
by johngg (Canon) on Nov 27, 2013 at 11:26 UTC

    Just an observation that there is a lot of wasted typing going on creating the array in the suggested answers. Doing

    ... my @array = qw{ create mount remove } x 20; ...

    would suffice.

    Cheers,

    JohnGG

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1064447]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2019-11-12 23:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Strict and warnings: which comes first?



    Results (66 votes). Check out past polls.

    Notices?