perl中的转换/数组数组

时间:2014-09-09 14:00:48

标签: arrays perl transform transpose

我坚持编写转换2d数组的Perl代码。

  • 数组的第一列始终为日期
  • 数组的第二列是排序的关键。
  • 数据位于数组“数据”中,按日期排序,然后按键排序。

  • 我的情况应该从下表中可以理解。将选择第二列中的唯一值,然后将其分为列标题(绿表)

它应该与列数或日期/键一起使用。

之前的结构

structure before

之后的结构

structure after 我的代码:

#creates filtered array of all the unique dates and its count
my @date          = @{ $data->[0] };
my @filtDate      = uniq @date;
my $countFiltDate = scalar @filtDate;
#unique list of keys
my @klic     = @{ $data->[1] };
my @filtKlic = uniq @klic;
#orders filtered keys
@filtKlic = sort @filtKlic;
my $countFiltKlic = scalar @filtKlic;
#count of columns
my $columnsCount = scalar @{$data};
#test code - counts how many new number columns to make.
my $columnsCountAfter = ( $columnsCount - 2 ) * $countFiltKlic;

#inserst filtered dates into first column
my $dataGraph;
for ( my $i = 0; $i < $countFiltDate; $i++ ) {
    $dataGraph->[0]->[$i] = @filtDate[$i];
}

#biggest loop with number of dates
for ( my $k = 0; $k < $countFiltDate; $k++ ) {
    my $l;
    my $c;
    #columns sount k $i
    for ( my $i = 0; $i < $columnsCount - 2; $i++ ) {
        #loop for different keys k $j
        for ( my $j = 0; $j < $countFiltKlic; $j++ ) {
            $l++;    #riadok v prvej tabulke
                     #EVERYTHING after this part is written horibly.
                     # I'm trying to make it work even
                     #if key values are missing.
            for ( my $m = 0; $m < 5; $m++ ) {
                if ( $data->[1]->[ $l - 1 ] eq $filtKlic[$j] ) {
                    print " [" . $data->[1]->[ ( $l - 1 ) ] . ',' . $filtKlic[$j] . "]";
                    $dataGraph->[ $l + $c ]->[$k] = $data->[ $i + 2 ]->[ ( ( $k * $countFiltKlic ) + $j ) ];
                    #print " [".$data->[1]->[$j].','.($filtKlic[($j)])."]-";
                    print " [" . ( $i + 2 ) . ',' . ( ( $k * $countFiltKlic ) + $j ) . "]-";
                    print " [" . ( $l + $c ) . ',' . $k . "]<br>";
                    $m = 5;    #just random number... i don't want to get infinite loops during testing

                } else {
                    if ( $m = 5 ) {
                        $l--;
                        $c++;
                    }
                    $j++;
                }
            }
        }
    }
}

my @nameStlpceKlic;
@nameStlpceKlic[0] = "date";
my $o;
for ( my $i = 0; $i < $columnsCount - 2; $i++ ) {
    foreach (@filtKlic) {
        my $o;
        $o++;
        @nameStlpceKlic[$o] = @filtKlic[ ( $o - 1 ) ] . $i;
    }
}

我有两个问题。

  1. 如果某些日期缺少部分密钥,如何确保此功能正常。
  2. 如何正确编写。我的代码太笨拙了。

2 个答案:

答案 0 :(得分:1)

以下是我解决此类问题的一般方法。

在第二个表格中,您按日期对数据进行分组,然后显示number1的值和number2的值。这应该为您提供有关如何组织数据结构以及打印索引所需的提示。

您当前的数据(我假设)存储在一个数组数组中。我懒得复制价值观,所以我用自己的价值制作了自己的AoA。我已经在代码中添加了评论,因此您可以看到我是如何处理此问题的。

my $arr = [
  ['date','key','number1','number2'],
  ['22.12.2013','1a','1a1-34567','1a2-1234567'],
  ['22.12.2013','2b','2b1-3249871','2b2-4597134'],
  ['22.12.2013','3c','3c1-1234567',''],
  ['22.12.2013','4d','4c1-3249871','4c2-4597134'],
  ['22.13.2013','1a','1a1-34567','1a2-1234567'],
  ['22.13.2013','2b','','2b2-4597134'],
  ['22.13.2013','3c','3c1-1234567','3c2-1234567'],
  ['22.13.2013','4d','4c1-3249871','4c2-4597134'],
];

# first, remove the first row, which contains the column headers.
my $col_h = shift @$arr;

my $data;
my $key_list;
foreach (@$arr) {
    my %hash;
    # use a hash slice with the column header array as keys
    # and the array as the values
    @hash{@$col_h} = @$_;
    # store this hash in a data hash indexed by date then key
    $data->{ $hash{date} }{ $hash{key} } = \%hash;
    # compile a separate hash with the keys in it
    $key_list->{ $hash{key} }++;
}

# make a sorted list of keys, ready for printing
my @key_list = sort keys %$key_list;

# remove the first two elements from the column headers ('date' and 'key')
splice(@$col_h, 0, 2);

# print out the header row for the table (I'm doing a simple tab-delim'd table)
print STDERR "Date\t";
# for each NUMBER from NUMBER1 ... NUMBERn
foreach my $c (@$col_h) {
    # print "keyID NUMBERn"
    map { print STDERR "$_ $c\t" } @key_list;
}
print STDERR "\n";

# Now print out the data itself. Sort by date...
foreach my $date (sort keys %$data) {
    print STDERR "$date\t";
    # for each NUMBER1 ... NUMBERn
    foreach my $header (@$col_h) {
        foreach my $key (@key_list) {
            ## print out the value OR - if there is no value
            print STDERR ( $data->{$date}{$key}{$header} || "-" ) . "\t";
        }
    }
    print STDERR "\n"; # end of the table row
}

输出(展开选项卡以显示):

Date        1a number1  2b number1  3c number1  4d number1  1a number2  2b number2  3c number2  4d number2  
22.12.2013  1a1-34567   2b1-3249871 3c1-1234567 4c1-3249871 1a2-1234567 2b2-4597134 -           4c2-4597134 
22.13.2013  1a1-34567   -           3c1-1234567 4c1-3249871 1a2-1234567 2b2-4597134 3c2-1234567 4c2-4597134

答案 1 :(得分:0)

我能够使用来自&#34;我惊恐的外星人&#34; 。 首先,不同的是我的数据以转置方式格式化为数组数组。

$arr1 = [ '2013-12-22', '2013-12-22' ]; 
$arr2 = [ 'Number1','Number2']; 
$arr3 = [ '2328942', '679204']; 
$arr4 = [ '1450398', '436713']; 

同样转换的数据应保存在数组中。我写了这段代码。 (它远非完美,如果有任何建议如何进一步提高它我会很高兴听到这些。)

####################
#transpose data 
my $datas = $args{DATA};
my $headers = $args{HEADERS};
my @rows = ();
my @transposed = ();
for my $row (@$datas) {
  for my $column (0 .. $#{$row}) {
    push(@{$transposed[$column]}, $row->[$column]);
  }
}

#################################
my @arr = @transposed;
# first, define headers.
my $col_h = $args{HEADERS};
my $data;
my $key_list;
foreach (@arr) {
    my %hash;
    # use a hash slice with the column header array as keys
    # and the array as the values
    @hash{@$col_h} = @$_;
    # store this hash in a data hash indexed by date then key
    $data->{ $hash{date} }{ $hash{key} } = \%hash;
    # compile a separate hash with the keys in it
    $key_list->{ $hash{key} }++;
}
# make a sorted list of keys, ready for printing
my @key_list = sort keys %$key_list;
# remove the first two elements from the column headers ('date' and 'key')
splice(@$col_h, 0, 2);

my @output;
my @header;
# print out the header row for the table (I'm doing a simple tab-delim'd table)
#print STDERR "Date\t";
push(@header, "Date\t");
# for each NUMBER from NUMBER1 ... NUMBERn
foreach my $c (@$col_h) {
    # print "keyID NUMBERn"
    map { push (@header,"$_ $c\t" )} @key_list;
    #map { print STDERR "$_ $c\t" } @key_list;
}
#print STDERR "<br>";
push (@output,\@header );
my $row;
my $column;
# Now print out the data itself. Sort by date...
foreach my $date (sort keys %$data) {
    #print STDERR "$date\t";
    $row++;
    my @line;
    push(@line, "$date");
    # for each NUMBER1 ... NUMBERn
    foreach my $header (@$col_h) {  
        foreach my $key (@key_list) {
            ## print out the value OR - if there is no value
            $column++;
            push (@line,( $data->{$date}{$key}{$header} || "-" ) . "\t");
            #print STDERR ( $data->{$date}{$key}{$header} || "-" ) . "\t";
        }
    }
    print STDERR "<br>"; # end of the table row
    $column = 0;    
    push (@output,\@line );
}

    my $x = 1;
   return @output;

}   

此代码有效,但有点难看。如果有更干净/更好的方法,请告诉我。