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

Hi I have a file with data like this.

-1 2 ereu 1 2 rerer 2 2 rere 3 2 eee 3 2 wwwe 9 2 qqewew 9 2 vvvgf -1 2 wwwew 4 3 wwew -9 3 wwss 6 3 jjuu 7 3 kkii 7 3 ggtyu 8 3 ffder 1 4 rrtrr 1 4 rree

If the values in 2nd column are same, calculate the minimum value in the first column and print corresponding lines. My desired output is;

-1 2 ereu -1 2 wwwew -9 3 wwss 1 4 rrtrr 1 4 rree

I wrote a code like this.

#! usr/bin/perl use warnings; use strict; my @a = <> ; my @b = (); foreach (@a) { push (@b, split(/ /)); } my $i = 0; my $j = 1; my $min = $b[0]; my $x = 0; while ($x++ < 150) { $j = $j+3; $i = $i+3; if ($b[$j] = $b[$j+3]) { if ($min > $b[$i]) { $min = $b[$i] } } } print "$min\n";

But the code ignores the condition if ($b$j = $b$j+3) and prints just the minimum value of first column. My idea was to use a regex involving the minimum value to print the corresponding lines. Obviously I am a newbie to Perl. Can experts help me please? thanks in advance.

Replies are listed 'Best First'.
Re: Selective Printing of Lines
by ambrus (Abbot) on Sep 16, 2011 at 09:09 UTC
    But the code ignores the condition if ($b[$j] = $b[$j+3])
    That's because = does assignment, not comparison.
Re: Selective Printing of Lines
by onelesd (Pilgrim) on Sep 15, 2011 at 22:31 UTC

    Had a beer at lunch and don't feel like doing my own work...

    use strict ; use warnings ; my @data = sort <DATA> ; my %min ; foreach (@data) { my ($col1, $col2, $col3) = split /\s+/, $_ ; $min{$col2} = $col1 if (! defined $min{$col2}) ; print $_ if ($col1 eq $min{$col2}) ; } __DATA__ -1 2 ereu 1 2 rerer 2 2 rere 3 2 eee 3 2 wwwe 9 2 qqewew 9 2 vvvgf -1 2 wwwew 4 3 wwew -9 3 wwss 6 3 jjuu 7 3 kkii 7 3 ggtyu 8 3 ffder 1 4 rrtrr 1 4 rree
      THank you all for excellent replies. All of them are working fine and now I am trying to 'decode' each of them :D. Hi onelesd, Can you please explain the if (! defined $min{$col2}) part of your code. Ever since you posted this code, I have been banging my head to understand the usage of defined and the unary operator !. Thanks in advance.

        See: perldoc -f defined

        defined EXPR defined Returns a Boolean value telling whether EXPR has a valu +e other than the undefined value "undef".

        ! negates the condition, so in natural language the condition is: "if $min{$col2} is not defined".

Re: Selective Printing of Lines
by Kc12349 (Monk) on Sep 15, 2011 at 22:40 UTC

    What is this use case here? Something beyond homework?

    my %min_data; for my $line (@lines) { my @columns = split ' ', $line; unless (exists $min_data{$columns[1]}) { $min_data{ $columns[1] } = {min=>$columns[0],lines=>[$line]}; } elsif ($columns[0] == $min_data{ $columns[1] }->{min}) { push @{ $min_data{ $columns[1] }->{lines} }, $line; } elsif ($columns[0] < $min_data{ $columns[1] }->{min}) { $min_data{ $columns[1] }->{lines} = [$line]; $min_data{ $columns[1] }->{min} = $columns[0]; } } for my $column_two (sort keys %min_data) { say for @{ $min_data{$column_two}->{lines} }; }

    onelesd's solution is far more simple

      Hopefully the teacher gives us both an A+
Re: Selective Printing of Lines
by Anonymous Monk on Sep 15, 2011 at 23:05 UTC

    Wish I had a beer...

    #!/usr/bin/perl use v5.12; use warnings; use strict; my %data; while (<DATA>) { my ($num, $key) = split; if (my $min = $data{$key}) { no warnings 'numeric'; $data{$key} .= $_ if $num == $min; $data{$key} = $_ if $num < $min; } else { $data{$key} = $_; } } print $data{$_} for sort keys %data; __END__