Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Array splitting

by Hopfi (Novice)
on Oct 31, 2012 at 21:37 UTC ( #1001748=perlquestion: print w/replies, xml ) Need Help??
Hopfi has asked for the wisdom of the Perl Monks concerning the following question:

Hi, Ive just tried to split up an array into 2 arrays sorted by the first letter of each word, but somehow it skips the if in the foreach loop. Any idea why? Heres the code:
#!/usr/bin/perl @not_sorted = qw(Ape Arg Beep Circus); @sorted = sort {$a cmp $b} @not_sorted; @A = (); @trash = (); foreach(@sorted) { if(substr($_,0,1) == 'A') { printf($_." added to A\n"); push(@A, $_); } else{ printf($_." added to trash!\n"); push(@trash, $_); } } print join(', ', @A)."\n"; print join(', ', @trash)."\n";

Replies are listed 'Best First'.
Re: Array splitting
by Kenosis (Priest) on Oct 31, 2012 at 21:42 UTC

    You need to use eq not ==,as the latter's used for numeric comparisons:

    if(substr($_,0,1) eq 'A') { ...


    Ape added to A Arg added to A Beep added to trash! Circus added to trash! Ape, Arg Beep, Circus

    Another option is to use a regex to check the beginning character:

    if(/^A/) { ...

    Also, consider doing the following for your print statements:

    ... print "$_ added to A\n"; ... print "$_ added to trash!\n";

      here is quick solution. See if it is useful for you.

      sub split_array { my @not_sorted = qw(Ape Arg Beep Circus); my @sorted = sort {$a cmp $b} @not_sorted; my @A = (); my @trash = (); map{$_ =~/^A.*/ ? push(@A,$_):push(@trash,$_)} @sorted; print "\n",@A,"\n"; print "\n",@trash,"\n"; }
Re: Array splitting
by AnomalousMonk (Canon) on Oct 31, 2012 at 22:00 UTC
    ... it skips the if in the foreach loop.

    When I run your OPed code, I see that the  else (false) clause of the conditional statement is skipped, not the  if (true) clause, which is always executed.

    The reason is that you are using a numeric  == comparison to test for string equality. You should use the  eq operator (see Equality Operators in perlop). Numeric comparisons of strings that have no leading decimal digits are always equal because such strings always evaluate to zero in numeric context.

    >perl -wMstrict -le "print 'A' == 'B'; " Argument "B" isn't numeric in numeric eq (==) at -e line 1. Argument "A" isn't numeric in numeric eq (==) at -e line 1. 1

    And BTW: using warnings would have alerted you to this problem, and using strict ain't a bad idea, either.

Re: Array splitting
by Perlbotics (Canon) on Oct 31, 2012 at 22:24 UTC


    use strict; use warnings; my @not_sorted = qw(Ape Arg Beep Circus); my @sorted = sort {$a cmp $b} @not_sorted; my @A = grep { /^A/ } @sorted; my @trash = grep { !/^A/ } @sorted; print join(', ', @A) , "\n"; print join(', ', @trash) , "\n";

    You can even include the printf(...) in the grep block, i.e. at the beginning since the result of the block should be determined by the filter expression.
    Have a look at split to split an array by position. From the title of your OP, I first thought you meant that...
Re: Array splitting
by johngg (Abbot) on Oct 31, 2012 at 22:50 UTC

    The { $a cmp $b } comparison is the default behaviour for sort so doesn't have to be mentioned specifically if you don't wish. You can populate your @A and @trash arrays in one go by eliminating the intermediate @sorted array and pushing onto the appropriate array using a ternary (see Conditional Operator).

    $ perl -Mstrict -Mwarnings -E' > my @notSorted = qw{ Beep Ape Circus Arg }; > my( @A, @trash ); > push @{ $_ =~ m{^A} ? \ @A : \ @trash }, $_ for sort @notSorted; > do { > local $" = q{, }; > say qq{@A}; > say qq{@trash}; > };' Ape, Arg Beep, Circus $

    I hope this is helpful.



      Alright. Thanks very much guys! Im more a C++ guy and not used to those different operations (like eq != ==).
Re: Array splitting
by tobyink (Abbot) on Nov 01, 2012 at 10:13 UTC
    use strict; use List::AssignRef; use List::MoreUtils qw( part ); my @not_sorted = qw(Ape Arg Beep Circus); (deref my @trash, deref my @A) = part { !!/^A/ } sort @not_sorted; print "Got A: @A\n"; print "Got trash: @trash\n";
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1001748]
Approved by state-o-dis-array
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2017-01-24 05:29 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (203 votes). Check out past polls.