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

hi monks, i have a string @array="PERLPERLPEBLPEBLPERL"; i wanna split the string into: "PERL" "PERL" "PEBL" "PEBL" "PERL". ie., split as 4 characters in each. i used 'SPLICE' function,like this,
for($i=0;$i<=scalar @array;$i++) { @ans=splice(@array,0,4); $join=join('',@ans); push(@answer,$join) } print "@answer\n";
but its leaving the last element. plz give me a solution. thanks.

Replies are listed 'Best First'.
Re: how to splice an array?
by gaal (Parson) on Oct 11, 2006 at 16:17 UTC
    You're starting with a string, so why put it in a one-element array?

    Anyway, here's a simple solution with regexps. It allows a trailing element that's too short. (If you don't want that, drop the "1," from the quantification.)

    my $str = "PERLPERLPEBLPEBLPERL"; my @parts = $str =~ /.{1,4}/g;
      Re Re: how to splice an array?sorry for this correction, but my out put from the previous step of the program gives me the @array containing those elements as a single character.can i operate on an array rather than starting with a string.

        Here is one way to do it with splice and join:

        use strict; use warnings; my $string = "PERLPERLPEBLPEBLPERL"; my @array = split( '', $string ); while( scalar @array ) { my $extracted = join( '', splice( @array, 0, 4 ) ); print "[$extracted]\n"; }

Re: how to splice an array?
by jasonk (Parson) on Oct 11, 2006 at 16:18 UTC

    Your array code is assuming that @array contains an array where each element is one letter from the string, which is not what it contains. You can make it contain that by using @array = split( '', "PERLPERLPEBLPEBLPERL" ); or you can just understand that you are dealing with a string, not an array, and take a different approach, such as...

    my $string = "PERLPERLPEBLPEBLPERL"; my @answer = ( $string =~ m/(.{4})/g ); print "@answer\n";

    We're not surrounded, we're in a target-rich environment!

      If it really is a string, substr and unpack could also be used. Here are three ways to do it:

      use strict; use warnings; my $string = "PERLPERLPEBLPEBLPERL"; my $offset = 0; my $step = 4; my @array; # unpack (could modify the pattern to use $step) @array = unpack( '(A4)*', $string ); # substr, original string intact while( $offset < length $string ) { push( @array, substr( $string, $offset, $step ) ); $offset += $step; } # substr, original string destroyed while( length $string ) { push( @array, substr( $string, 0, $step, '' ) ); }

Re: how to splice an array?
by Melly (Chaplain) on Oct 11, 2006 at 16:30 UTC

    Maybe it's just me, but this doesn't seem to make any sense - you are putting your string into the first element of your array, but nothing into subsequent elements - why not just use a scalar? And what is your splice meant to do?

    Then you are creating a new string (just the one) and pushing that into element 0 of another array. Again why not use a scalar?

    Are you sure you haven't misunderstood the class assignment? ;)

    $scalar="PERLPERBPERCPERD"; $homework = join ' ', $scalar =~ /(.{4})/g; print $homework;
    Tom Melly, tom@tomandlu.co.uk
a clearer query for how do i splice an array
by heidi (Sexton) on Oct 11, 2006 at 16:41 UTC
    sorry for not being clear in my previous post. i have an array
    @array="P H A G E P H A G E P Q K R E P H A G E P W S Q E P H A G E P +R D L E P H A G E"
    i cant help it being this way, coz this is the out put which i get from the previous step of the program. i got to split this into 5 characters each and then compare whether any of the pattern matches with "PHAGE". so i want to make it like
    PHAGE PHAGE PQKRE PHAGE PWSQE PHAGE PRDLE PHAGE.
    and then pattern match it PHAGE. finally i should be printing only 5 PHAGES. hope its clear.

      Are you sure @array is holding nothing but a string? If so why are you using an array?

      my $str = "P H A G E P H A G E P Q K R E P H A G E P W S Q E P H A G E + P R D L E P H A G E"; $str =~ s/\s+//g; my @words = $str =~ /.{1,5}/g;

      Or do you mean:

      my @array = ('P', 'H', 'A', 'G', 'E', 'P', 'H', 'A', 'G', 'E', 'P', 'Q', 'K', 'R', 'E', 'P', 'H', 'A', 'G', 'E', 'P', 'W', 'S', 'Q', 'E', 'P', 'H', 'A', 'G', 'E', 'P', 'R', 'D', 'L', 'E', 'P', 'H', 'A', 'G', 'E'); my @words; while (@array) { push(@words, join('', splice(@array, 0, 5))); }

      Then, for the second part,

      foreach (@words) { next unless $_ eq 'PHAGE'; print("$_\n"); }

      What task are you trying to accomplish? Are you simply trying to count the occurences of runs of P H A G E? Do the occurances have to happens at particular points in the string (for instance, starting at a position that is a multiple of 5)?

      If you have a string (or can make it a string), you can use index to find them and count them. Remember that index returns -1 when it doesn't find the substring, and that's a true value.

      #!/usr/bin/perl use strict; use warnings; my $string = "PHAGEPHAGEPQKREPHAGEPWSQEPHAGEPRDLEPHAGE"; my $substring = "PHAGE"; my $count = 0; my $last_pos = -1; NAKED: { $last_pos = index( $string, $substring, $last_pos + 1 ); last if $last_pos == -1; print "Found $substring at $last_pos\n"; $count++; redo; } print "Found $count instances of $substring\n"; __OUTPUT__ Found PHAGE at 0 Found PHAGE at 5 Found PHAGE at 15 Found PHAGE at 25 Found PHAGE at 35 Found 5 instances of PHAGE

      If you have an array and you need to find the occurences among consecutive array entries (perhaps, because the array is huge and you want to avoid a lot of copying), you can do the same sort of thing, although you have to invent your own code to find the indices. Scoot along the array and try the subarray at each position. Once it fails, move the starting position (that's $offset) and try again. Do that until you run out of array.

      #!/usr/bin/perl use strict; use warnings; my @array = split //, "PHAGEPHAGEPQKREPHAGEPWSQEPHAGEPRDLEPHAGE"; my @subarray = split //, "PHAGE"; my $offset = 0; my $count = 0; NAKED: { foreach my $index ( 0 .. $#subarray ) { next if $array[ $offset + $index ] eq $subarray[ $index ]; $offset += 1; redo NAKED; } print "Found @subarray at $offset\n"; $count++; $offset += @subarray; last if $offset + @subarray > @array; redo; } print "Found $count instances of @subarray\n"; __OUTPUT__ Found P H A G E at 0 Found P H A G E at 5 Found P H A G E at 15 Found P H A G E at 25 Found P H A G E at 35 Found 5 instances of P H A G E
      --
      brian d foy <brian@stonehenge.com>
      Subscribe to The Perl Review
      Maybe you are confused about the perl syntax for initializing an array. Did you mean something like this:
      @array = qw/P H A G E P H A G E P Q K R E P H A G E P W S Q E P H A G +E P R D L E P H A G E/;
      The "qw" quoting operator provides a short-cut for placing quotations marks around each space-delimited token (and putting commas between them as well). So what I've shown above will cause @array to contain 40 elements, with each element being a single letter.

      By contrast, your  @array = "P H A G E ..."; approach causes @array to contain only one element, which is a string of 79 characters (40 letters separated by 39 spaces).

      So if your "previous step of the program" (whatever that may be) is really producing an array of 40 elements with one letter per element, maybe the following would do what you want:

      my $start = 0; my $end = 4; while ( $end <= $#array ) { my $string = join( "", @array[$start..$end]; if ( $string eq 'PHAGE' ) { print "$string found in elements $start .. $end\n"; } $start += 5; $end += 5; }