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

In my @{$data1{$datafile}}, I have something like

abc abc1 abc2
abc abc1 abc3 abc5
abc2 abc3 abc5 abc7 abc9 abc10
abc1 abc2 abc3 abc4 abc5 abc6

so if I run a below code, it does the job and print
my @fields = @{$data1{$datafile}}; # next if (length(map { s/\s+//g, $_ } @fields) < 15); print map { s/\s+//g, $_ } @fields;
abcabc1abc2
abcabc1abc3abc5
abc2abc3abc5abc7abc9abc10

and so on..
But if I try to discard anything shorter than length 15 and print that is above 15 , it doesn't work.. what am I doing wrong?
my @fields = @{$data1{$callid}}; next if (length(map { s/\s+//g, $_ } @fields) < 15); print map { s/\s+//g, $_ } @fields;

Replies are listed 'Best First'.
Re: map question
by GrandFather (Saint) on Jul 28, 2007 at 23:42 UTC

    next won't do very much for you outside of a loop. Using tools such as map with an implicit loop do not allow the use of next. However you can combine map and grep to achieve what you want:

    use strict; use warnings; my @fields = ( 'abc abc1 abc2', 'abc abc1 abc3 abc5', 'abc2 abc3 abc5 abc7 abc9 abc10', 'abc1 abc2 abc3 abc4 abc5 abc6', ); print grep {length > 15} map {s/\s+//g; "$_\n"} @fields;

    Prints:

    abcabc1abc3abc5 abc2abc3abc5abc7abc9abc10 abc1abc2abc3abc4abc5abc6

    with the further advantage that you don't have to maintain the same piece of code in multiple places.


    DWIM is Perl's answer to Gödel
      Is this suppose to be print ONLY if length of it is greater than 15 ? Currently, it's not printing anything..
      What I want is after going through some sort of code,
      it will take out all the \s+ and put them together
      abc abc1 abc2 abc3
      as

      abcabc1abc2abc3

      and then see if it's length is greater than 15
      and print ONLY if length is greater than 15, if not, discard
      print grep {length > 15} map {s/\s+//g; "$_\n"} @fields;
      Here is my entire code
      #!/usr/bin/perl -w use strict; my $ncb = $/; my $cbn = $"; $/ = "\n\n"; $" = "\n"; my $yahoo = shift @ARGV; open FH, "$yahoo" or die "can't open $!"; my $callid; my $sipm; my %data1 = (); my $count = 0; my @fields1; while (<FH>) { chomp; if (m/###/) { next; } unless (m{(?:^\bSIP\/2\.0 \b)?(\d\d\d|^[A-Z]{3,6} ).*(Call-ID: +[\S]{25,80})[^ ]+: .*}s) { $count++; next; } ($sipm,$callid) = ($1,$2); push (@{$data1{$callid}}, $sipm); } close FH; $/ = $ncb; $" = $cbn; print "There were $count which could not detect\n"; #foreach $callid (sort keys %data1) { # my @fields = @{$data1{$callid}}; # foreach (@fields) { # print map { # ( my $x = $_ ) =~ s/\s+//g; # length( $x ) < 15 ? () : $x; # } @{ $data1{ $callid } }; # } #} foreach $callid (sort keys %data1) { my @fields = @{$data1{$callid}}; print grep {length > 15} map {s/\s+//g; "$_\n"} @fields; }

        If you are not seeing the data you expect being printed then the data is probably no as you expect. Try using Data::Dump::Streamer to examine the data structure that you actually have.


        DWIM is Perl's answer to Gödel
Re: map question
by jwkrahn (Abbot) on Jul 29, 2007 at 00:25 UTC
    It looks like you want something like:
    print map { ( my $x = $_ ) =~ s/\s+//g; length( $x ) < 15 ? () : $x; } @{ $data1{ $datafile } };
Re: map question
by FunkyMonk (Bishop) on Jul 28, 2007 at 23:43 UTC
    How can you have next without a loop? Please, show us all the relevant code.

    Having said that, length expects a scalar, so your map is evaluated in scalar context, returning the number of elements it processed. It is that number that is used as the argument to length. So, unless @fields contains 10 ** 15 elements, it's length will be less than 15 and next will be executed.

    <clpm>
    Please, for your next question, give us a small, complete program that we can run, rather than a snippit of something bigger, especially at this time on Saturday night ;)
    </clpm>

Re: map question
by dewey (Pilgrim) on Jul 28, 2007 at 23:40 UTC
    What about it doesn't work? This looks like a code fragment, and it would be easier to answer if I knew more about your problem and your code.

    I haven't investigated closely, but using s/// inside map may be tripping you up: modifying $_ during map modifies the array you're mapping over. Running that same map code twice doesn't make much sense to me.

    ~dewey