如何修复程序outfiles的顺序?

时间:2016-07-07 16:59:00

标签: perl

所以我有一个程序可以根据两列输入排序数据(按降序递增),并将这些数据输出到一个文本文件中,该文件将数据插入文本文件中。我遇到的问题是它不会以与读入程序相同的顺序产生输出。

以下是数据集的示例:

2, 1, 20, 1, 10, 28.5714285, 0, 
2, 1, 72, 3, 7, 20, 0, 
2, 2, 20, 3, 19, 52.7777777, 0, 
5, 1, 66, 3, 199, 21.1927582, 0, 
5, 1, 5, 2, 153, 16.2939297, 0, 

以下是无序输出的示例:

fci
u
csno=51 svgrp=0 antfc= 2
cdmanbr_list1.ncs_c[1]= 51
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u
u
csno=66 svgrp=0 antfc= 2
cdmanbr_list1.ncs_c[1]= 66
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u
u
csno=51 svgrp=0 antfc= 3
cdmanbr_list1.ncs_c[1]= 51
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u

注意第三个“csno”(51)的值是如何小于第二个“csno”值(66)。即使有2个相同值的“csno”,“antfc”值也不同。所需的输出如下:

fci
u
csno=51 svgrp=0 antfc= 2
cdmanbr_list1.ncs_c[1]= 51
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u
u
csno=51 svgrp=0 antfc= 3
cdmanbr_list1.ncs_c[1]= 51
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u
u
csno=66 svgrp=0 antfc= 2
cdmanbr_list1.ncs_c[1]= 66
cdmanbr_list1.nghbrantf[1]= 1
cdmanbr_list1.pilot_pn[1]=
cdmanbr_list1.pgn_c[1]= 0
u

以下是该计划的副本:

#!/usr/bin/perl
use POSIX qw(strftime);

( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
  localtime(time);

my $bdate = sprintf( "%02d%02d%02d", $mon + 1, $mday - 7, $year - 100 );
my $edate = sprintf( "%02d%02d%02d", $mon + 1, $mday - 1, $year - 100 );

my $newresult = "/home/user/newresults/recommended_$bdate-$edate.csv";
my $script    = "/home/user/update_scripts/update_$bdate-$edate.txt";

my $h;
my $k;
my $n;
my $fh = undef;
open( $fh,  '<', $newresult ) or die $!;
open( $fsh, '>', $script )    or die $!;
print $fsh "fci\n";
while ( my $line = <$fh> ) {
    next if $. < 2;
    chomp $line;
    my @array = split( /\,/, $line );
    my $key = "csno=$array[0] svgrp=0 antfc=$array[1]";
    push( @{ $h->{$key} }, $array[6] );
    push( @{ $k->{$key} }, $array[2] );
    push( @{ $n->{$key} }, $array[3] );
} ## end while ( my $line = <$fh> )

foreach my $key ( keys %{$h} ) {
    print $fsh "u\n";
    print $fsh "$key\n";
    if ( @{ $h->{$key} } <= 12 ) {
        for ( my $i = 1 ; $i <= @{ $h->{$key} } ; $i++ ) {
            my $m = $i - 1;
            print $fsh "cdmanbr_list1.ncs_c[$i]=${$k->{$key}}[$m]\n";
            print $fsh "cdmanbr_list1.nghbrantf[$i]=${$n->{$key}}[$m]\n";
            print $fsh "cdmanbr_list1.pilot_pn[$i]=\n";
            print $fsh "cdmanbr_list1.pgn_c[$i]=${$h->{$key}}[$m]\n";
        } ## end for ( my $i = 1 ; $i <=...)
        for ( my $i = @{ $h->{$key} } + 1 ; $i < 13 ; $i++ ) {
            my $m = $i - 1;
            print $fsh "cdmanbr_list1.ncs_c[$i]=\n";
            print $fsh "cdmanbr_list1.nghbrantf[$i]=\n";
            print $fsh "cdmanbr_list1.pilot_pn[$i]=\n";
            print $fsh "cdmanbr_list1.pgn_c[$i]=\n";
        } ## end for ( my $i = @{ $h->{$key...}})
    } ## end if ( @{ $h->{$key} } <=...)
    print $fsh "u\n";
} ## end foreach my $key ( keys %{$h...})

1 个答案:

答案 0 :(得分:0)

问题的根源在于

foreach my $key (keys%{$h}){

您期望哈希的键将以某种预定义的顺序排列。这不是哈希的工作方式。

2个合理的解决方案是:

  • (针对工作量进行优化)如果您知道输入文件已根据需要进行排序,请在构建$key时将%$h推送到数组中,然后通过它进行交互。即。

    foreach my $key (@keyorder) {

  • (针对内存进行优化)获取(显然)未排序的密钥列表并对其进行排序:

    foreach my $key (sort { ### comparison here ### } keys %{$h}) {

您的比较可能采用以下形式:((split $a, /=/)[1] <=> (split $b, /=/)[1]) || ((split $a, /=/)[-1] <=> (split $b, /=/)[-1]),具体取决于您的分类要求的详细信息。

虽然C样式for循环在Perl中占有一席之地,但你的内部循环可以从一些惯用的Perl中受益。

for my $i ( 1 .. @{$h->{key}} ) {
  #stuff
}
for my $i ( @{$h->{key}}+1 .. 12 ) {
  #other stuff
}