如何从Perl中的数组中获取最大值?

时间:2016-05-20 02:38:41

标签: perl

我有一个输入源,如下所示。我想要做的是将每个Layer行的数值捕获到一个数组中,然后打印出最大值。

输入

MACRO cell_1
 size 0.1 by 0.1 ; 

 pin a
 (....same topology as pin vcc)
 END a

 pin b
 (.....same topology as pin vcc)
 END b

 Pin vcc
  aaaa
  bbbb
  Port
   Layer m2 ;
  END
  CCC
  DDD
  Port 
   Layer m1 ;
  END
  EEE
  FFF
  Port
   Layer m0 ;
  END
 END vcc

 pin d
 (....same topology as pin vcc)
 END d
END cell_1

MACRO cell_2
(repeated)
END cell_2 

我的代码:

foreach my $file ( @files ) {   # @files = multiple path  of abc/def/fgh/cell_lef

    open( INFILE, "<$file" ) || die "Can not open stdcell_file\n";
    my @lines = <INFILE>;
    close INFILE;

    $init = 1;
    $delimiter =~ /^$/;      # between each MACRO. haven't utilize this yet

    foreach (@lines) {

        if ( $init ) {
            $path = 1;
            $init = 0;
            @num  = ();
        }

        if ( $path ) {

            if ( /MACRO\s+(\S+) /) {
                $cellname = $1; print "$cellname\n";
            }

            if ( /SIZE\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
                $footprint_x = $1;
                $footprint_y = $3;
                print "$footprint_x $footprint_y\n";
            }

            if ( /PIN vcc/ .. /END vcc/ ) {

                #grab the highest value from layer (m*)
                #print "max layer = m*"
            }

            $init = 1;
        }
    }
}

预期输出

cell_1
0.1 0.1
m2

cell_2
0.2 0.2
m3

我试图使用的代码:

if ( /PIN vcc/../END vcc/ ) {
    if ( /LAYER\s+m(\S+) / ) {
        push(@num, $1);
        print "@num";
    }                               
}    

到目前为止我的代码存在的问题是,当我打印@num的值时,所有值都以字符串(210)而不是单个元素连接在一起:2 1 0 - 所以我无法进行排序以获得最大值。

更新 :我不确定如何将while集成到我的代码中,因为我使用foreach作为我的主循环

5 个答案:

答案 0 :(得分:2)

您的代码正在捕获数字,只是您正在打印整个数组。打印数组时,Perl对数组元素的默认分隔符是"",即没有 - 所以,它看起来像一个单独的字符串,但是每个字符串旁边都打印了三个(或多个)元素其他没有分隔符。

您可以使用while (<>) {在Unix过滤器样式中逐行迭代输入。您可以打开&#34;扫描模式&#34;当&#34; PIN vcc&#34;找到并在&#34; END vcc&#34;找到了。之后,使用正则表达式搜索图层线,但始终使用&#39;扩展模式&#39; /x所以你可以在你的正则表达式中使用空格。

由于用于切换模式和捕获图层编号的正则表达式是互斥的,因此您可以在检查成功后让其他检查发生 - 只要知道如果将来的更改导致重叠的情况,您需要做当其中一个正则表达式成功时,next

最后,List::Util是一个核心模块,所以你也可以从中获取max function;

use v5.12;
use warnings;
use List::Util qw( max );

my @num ;
my $scanning = 0;
while (<>) {
    $scanning = 1  if /PIN vcc/ ;
    $scanning = 0  if /END vcc/ ;
    next unless $scanning ;
    push @num, $1  if /Layer \s+ m (\d+) /x ;
}
say "Max layer number found: ", max(@num) ;

答案 1 :(得分:1)

或者只需使用sort功能即可。

my @values ;
while (<DATA>) 
{    
       push (@values , $1) if (/Layer\s+m(\d+)\s;/);
}
my ($max) = sort{$b <=> $a} @values ;
print "$max\n";

__DATA__
Pin vcc
aaaa
bbbb
Port
  Layer m3 ;
END
CCC
DDD
Port 
  Layer m1 ;
END
EEE
FFF
Port
  Layer m0 ;
END

使用sort函数并将第一个结果存储到包含变量$max的列表中。

答案 2 :(得分:0)

my @data = <DATA> ;
my @num ;

foreach (@data) {
 push @num, $1 if /Layer\s+m(\S+)/ ;
} 
# home made max() - sorts an anonymous array and prints the last element
print [ sort { $a <=> $b } @num ]->[-1] , "\n" ;

__DATA__
Pin vcc
aaaa
bbbb
Port
  Layer m2 ;
END
CCC
DDD
Port 
  Layer m1 ;
END
EEE
FFF
Port
  Layer m0 ;
END
END vcc

答案 3 :(得分:0)

使用map从文件中提取数字。 sort数字并获得最大数量。

#!/usr/bin/perl
use strict;
use warnings;

my $max = (sort{$b <=> $a }map{/Layer\s+m(\d+)/} <DATA>)[0];
print $max,"\n";

__DATA__
Pin vcc
aaaa
bbbb
Port
  Layer m3 ;
END
CCC
DDD
Port 
  Layer m1 ;
END
EEE
FFF
Port
  Layer m0 ;
END

答案 4 :(得分:0)

首先,如果您只查找最大值,则无需存储所有值;第二,在循环结束后打印最大值,

my $max = "-inf";
if (/PIN vcc/ .. /END vcc/) {
    $max = $1 if /LAYER\s+m(\S+)/ and $max < $1;
}

# ..
print $max, "\n";