perl:按顺序对列中的数字进行排序

时间:2016-01-14 20:36:43

标签: perl sorting

我想在最后一栏中对我的数字进行排序,$ en以相反的顺序排序(从最小值到更大值)。更多,我指定了我的数字。它们达到0并且只是负数。

我的脚本如下:

!/usr/bin/perl -w

use strict;

my $list=$ARGV[0];


open(LST,$list) or die;

my $time=0;

my @id_table;
my @nr_table;
my @energy;

open(GRO,">waters.gro") or die;

while(<LST>) {
  my $pdb_file=$_;
  chomp $pdb_file;
  my $pdb_id=substr $pdb_file,0,4;
  open(PDB,$pdb_file) or die;
  while(<PDB>) {
      my $line=$_;
      my ($w_id, $x, $y, $z, $en) = (split(/\s+/, $line))[1, 5, 6, 7, 8];
      next if $en >= 0;
      my @energy = sort {$b <=> $a} $en;
      print GRO "moja woda t=   $time \n";
      printf(GRO "%5d\n",1);
      printf(GRO "    1SOL     OW    1%8.3f%8.3f%8.3f%8.3f\n",$x/10.0,$y/10.0,$z/10.0,$en);
      print GRO " 20.0 20.0 20.0\n";
      $id_table[$time]=$pdb_id;
      $nr_table[$time]=$w_id;
      $time++;
  }
  close PDB;
}
close GRO;

不幸的是,我对分类的想法并不奏效。我是Perls&#39;的初学者。脚本。在我的输出中,我想按递增顺序排序值。

提前谢谢你。 玛尔塔

我的输入文件:

ATOM    367  OH2 HOH   367      -2.010   7.370  -7.369   -6.52
ATOM    491  OH2 HOH   491       0.990   8.370  -8.369   -2.24
ATOM    652  OH2 HOH   652       5.490  -6.130   2.631    2.98
ATOM    689  OH2 HOH   689       6.490 -15.130   8.631   -4.23
ATOM    738  OH2 HOH   738       7.490  19.870  -8.369    3.38
ATOM    793  OH2 HOH   793       8.990  -2.630 -22.869   -2.29
ATOM    857  OH2 HOH   857      10.490  13.370  -5.869   -1.31
.
.
.

行动结束后,我得到了输出(没有排序行):

moja woda t=   0 
        1
        1SOL     OW    1  -0.344   0.437   0.633  -9.290
     20.0 20.0 20.0
    moja woda t=   1 
        1
        1SOL     OW    1  -0.194   0.537  -0.767  -2.990
     20.0 20.0 20.0
    moja woda t=   2 
        1
        1SOL     OW    1  -0.044   0.287   0.333   4.960
     20.0 20.0 20.0
    moja woda t=   3 
        1
        1SOL     OW    1   0.106   0.837  -0.817  -1.300
     20.0 20.0 20.0
    moja woda t=   4 
    .
    .
    .

我想按顺序订购我的数据(每行依赖于$ en列)。我想我应该创建一个新阵列,但我不知道我应该在脚本中确切地确定排序的确切位置。

1 个答案:

答案 0 :(得分:1)

我的代码存在一些问题,我已经改变了

你的排序不起作用的原因是声明

my @energy = sort {$b <=> $a} $en

的值归类为$en并将其放入@energy。只有一个值,显然没什么可做的。您必须一次所有要排序的数据

只要您的文件大小合适,通常的方法是将文件读入一个数组,每个元素有一条记录,然后对该数组进行排序。我已经在下面的程序中完成了。数组@pdb_data的每个元素都包含对您最初拥有它们的顺序的五个字段数组的引用

$time值作为每个记录的第六个字段添加,因为这必须在排序之前完成。最后,数组按$en - 第五个字段的递增顺序排序。 (顺便说一句,标准排序顺序是从较小的值到较大的值。这是您想要的正常排序,而不是相反的排序。)

然后,可以在简单的for循环中打印已过滤和排序的数组中的数据。作业

my ( $w_id, $x, $y, $z, $en, $time ) =  @$_

从最初的每个数组元素中拉出字段,最后添加一个时间字段

我一直无法在没有任何数据的情况下测试它,但程序确实编译了

#!/usr/bin/perl

use strict;
use warnings 'all';

my ($list_file) = @ARGV;

open my $lst_fh, '<', $list_file or die qq{Unable to open "$list_file" for input: $!};

my $gro_file = 'waters.gro';
open my $gro_fh, '>', $gro_file or die qq{Unable to open "$gro_file" for input: $!};

while ( my $pdb_file = <$lst_fh> ) {

    chomp $pdb_file;
    open my $pdb_fh, '<', $pdb_file or die $!;

    my @pdb_data;
    my $time = 0;

    while ( <$pdb_fh> ) {

        my @record = ( split )[ 1, 5, 6, 7, 8 ];

        next unless $record[4] < 0;

        push @record, $time++;

        push @pdb_data, \@record;
    }

    @pdb_data = sort { $a->[4] <=> $b->[4] } @pdb_data;

    my $stdout = select $gro_fh;

    for ( @pdb_data ) {

        my ( $w_id, $x, $y, $z, $en, $time ) =  @$_;

        printf "moja woda t=   %d\n", $time;
        printf "%5d\n", 1;
        printf "    1SOL     OW    1%8.3f%8.3f%8.3f%8.3f\n", $x/10.0, $y/10.0, $z/10.0, $en;
        print  " 20.0 20.0 20.0\n";
    }

    select $stdout;
}

close $gro_fh or die $!;


更新

此变体在排序和打印之前读取列表文件中所有文件的所有数据。时间值按$ne字段

的顺序应用
#!/usr/bin/perl

use strict;
use warnings 'all';

my ($list_file) = @ARGV;
my $gro_file = 'waters.gro';

open my $lst_fh, '<', $list_file or die qq{Unable to open "$list_file" for input: $!};

my @pdb_data;

while ( my $pdb_file = <$lst_fh> ) {

    chomp $pdb_file;
    open my $pdb_fh, '<', $pdb_file or die $!;

    while ( <$pdb_fh> ) {

        my @record = ( split )[ 1, 5, 6, 7, 8 ];

        next unless $record[4] < 0;

        push @pdb_data, \@record;
    }
}


@pdb_data = sort { $a->[4] <=> $b->[4] } @pdb_data;

open my $gro_fh, '>', $gro_file or die qq{Unable to open "$gro_file" for input: $!};
select $gro_fh;

my $time = 0;

for ( @pdb_data ) {

    my ( $w_id, $x, $y, $z, $en ) =  @$_;

    printf "moja woda t=   %d\n", $time++;
    printf "%5d\n", 1;
    printf "    1SOL     OW    1%8.3f%8.3f%8.3f%8.3f\n", $x/10.0, $y/10.0, $z/10.0, $en;
    print  " 20.0 20.0 20.0\n";
}

close or die $!;

输出

moja woda t=   0
    1
    1SOL     OW    1  -0.201   0.737  -0.737  -6.520
 20.0 20.0 20.0
moja woda t=   1
    1
    1SOL     OW    1   0.649  -1.513   0.863  -4.230
 20.0 20.0 20.0
moja woda t=   2
    1
    1SOL     OW    1   0.899  -0.263  -2.287  -2.290
 20.0 20.0 20.0
moja woda t=   3
    1
    1SOL     OW    1   0.099   0.837  -0.837  -2.240
 20.0 20.0 20.0
moja woda t=   4
    1
    1SOL     OW    1   1.049   1.337  -0.587  -1.310
 20.0 20.0 20.0