http://www.perlmonks.org?node_id=930184

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

use warnings; use strict; my @bundle1 = qw/ch3 ch4 ch6/; my %bundle1 = ( ch3 => 0, ch4 => 0, ch6 => 0, ); my $i = 0; my @charges = qw/ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch1 ch2 ch3 ch4 ch5 c +h1 ch2 ch6 ch7 ch4 ch3 ch9 ch2 ch4/; foreach my $bundle (@bundle1) { foreach my $charge (@charges) { if ($bundle eq $charge) { $i++; $bundle1{$bundle} = $i; print $bundle1{$bundle}; } } }
Now my main goal I am trying to accomplish is if @bundle1 is found in @charges, then remove the corresponding @bundle1 in @charges and replaced with 'chx'.

So input is--> ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch1 ch2 ch3 ch4 ch5 ch1 ch2 ch6 ch7 ch4 ch3 ch9 ch2 ch4

So output is--> ch1 ch2 ch5 chx ch7 ch8 ch1 ch2 ch5 ch1 ch2 chx ch7 ch4 ch3 ch9 ch2 ch4

Replies are listed 'Best First'.
Re: array within an array
by toolic (Bishop) on Oct 07, 2011 at 13:49 UTC
    Your text description does not match your stated output, but I think you are looking for something like this...
    use warnings; use strict; my @charges = qw/ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch1 ch2 ch3 ch4 ch5 ch1 ch2 ch6 ch7 ch4 ch3 ch9 ch2 ch4/; my %bundle1 = map { $_ => 0 } qw(ch3 ch4 ch6); for (@charges) { if (exists $bundle1{$_}) { print "chx "; } else { print "$_ "; } } print "\n"; __END__ ch1 ch2 chx chx ch5 chx ch7 ch8 ch1 ch2 chx chx ch5 ch1 ch2 chx ch7 ch +x chx ch9 ch2 chx
      I got a bit nearer with
      #! /usr/perl/bin use warnings; use strict; use Data::Dumper; use warnings; use strict; my @charges = qw/ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch1 ch2 ch3 ch4 ch5 ch1 ch2 ch6 ch7 ch4 ch3 ch9 ch2 ch4/; my %bundle1 = map { $_ => 0 } qw(ch3 ch4 ch6); my $i; for (@charges) { if (exists $bundle1{$_}) { $i++; if ($i == 3){ print "chx "; $i = 0; } } else { print "$_ "; } } print "\n"; __END__ ch1 ch2 ch5 chx ch7 ch8 ch1 ch2 ch5 ch1 ch2 chx ch7 ch9 ch2 chx
      But it assumes a lot and the last chx is wrong.
        This code is almost what I need, but using a count will not work (actually tried that) :). I only what the elements in @charges removed and replaced with chx if all the keys in %bundle1 are found. So that last element ch4 was replaced and it should not. This is where I am stuck.

      From the example output it looks to me like the sequence "ch3 ch4 ch6" should be replaced with 'chx' even if there are other things mixed in.

        correct
Re: array within an array
by aartist (Pilgrim) on Oct 07, 2011 at 14:40 UTC
    You need to define 'charges' properly. Do you mean to say?
    @charges = ( [qw/ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8/], [qw/ch1 ch2 ch3 ch4 ch5/], [qw/ch1 ch2 ch6 ch7/], [qw/ch4/], [qw/ch3 ch9/], [qw/ch2 ch4/], )
    I am inclined to provide this as you said in other comment that last ch4 should not be replaced with 'chx'.
      no @charges is just one long list. I am trying to simulate a groups of actually charges for one account, using this trivial example.

      ch3 ch4 ch6 as a 'group' are replaced as 'chx' in list(array) in @charges.

        I think this does what you want:

        use warnings; use strict; my @charges = qw/ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch1 ch2 ch3 ch4 ch5 ch1 ch2 ch6 ch7 ch4 ch3 ch9 ch2 ch4/; my %bundle1 = map { $_ => 0 } qw(ch3 ch4 ch6); my %b = %bundle1; my @final; my @del; for (@charges) { if (exists $bundle1{$_}) { delete $b{$_}; if (!keys %b) { # seen them all, so reset %b = %bundle1; @del = (); push@final,'chx'; } else { # keep it, in case not all are seen push@del,$_; } } else { push@final,$_; } } push@final,@del; # add back any remainders print "@final\n"; __OUTPUT__ ch1 ch2 ch5 chx ch7 ch8 ch1 ch2 ch5 ch1 ch2 chx ch7 ch9 ch2 ch4 ch3 ch +4

        One possible problem: it will slightly alter the order of your list if a partial bundle is seen.

Re: array within an array
by Anonymous Monk on Oct 07, 2011 at 20:13 UTC

    Perhaps a regular expression:

    for ("@charges") { s/ch3 ((?:ch[^346] )*)ch4 ((?:ch[^346] )*)ch6/${1}${2}chx/g; say; }