Arrays perl中的Transform/pivot数组

Arrays perl中的Transform/pivot数组,arrays,perl,transform,transpose,Arrays,Perl,Transform,Transpose,我一直在写转换2d数组的Perl代码 数组的第一列始终是日期 数组的第二列是排序的键 数据位于数组“Data”中,按日期排序,然后按键排序 我的情况应该可以从下面的表格中理解。将选择第二列中的唯一值,然后将其划分为列标题(绿色表格) 它应该与列数或日期/键一起使用 结构之前 结构后 我的代码: #创建所有唯一日期及其计数的筛选数组 我的@date=@{$data->[0]}; my@filtDate=uniq@date; my$countFiltDate=标量@filtDate; #唯一

我一直在写转换2d数组的Perl代码

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

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

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

结构之前

结构后

我的代码:

#创建所有唯一日期及其计数的筛选数组
我的@date=@{$data->[0]};
my@filtDate=uniq@date;
my$countFiltDate=标量@filtDate;
#唯一的密钥列表
my@klic=@{$data->[1]};
my@filtKlic=uniq@klic;
#订单筛选键
@filtKlic=排序@filtKlic;
my$countFiltKlic=标量@filtKlic;
#列数
my$columnsCount=scalar@{$data};
#测试代码-计算要生成的新数字列数。
my$columnsCountAfter=($columnsCount-2)*$countFiltKlic;
#将筛选的日期插入第一列
我的$dataGraph;
对于(my$i=0;$i<$countFiltDate;$i++){
$dataGraph->[0]->[$i]=@filtedate[$i];
}
#具有日期数的最大循环
对于(my$k=0;$k<$countFiltDate;$k++){
我的$l;
我的$c;
#一元新台币
对于(我的$i=0;$i<$columnsCount-2;$i++){
#循环不同的键k$j
对于(my$j=0;$j<$countFiltKlic;$j++){
$l++#riadok v prvej tabulke
#这一部分之后的一切都写得很好。
#我正在努力使它更有效
#如果缺少键值。
对于(我的$m=0;$m<5;$m++){
如果($data->[1]->[$l-1]eq$filteklic[$j]){
打印“[”$data->[1]->[($l-1)],”.$filtKlic[$j].“]”;
$dataGraph->[$l+$c]->[$k]=$data->[$i+2]->[($k*$countFiltKlic)+$j];
#打印“[”$data->[1]->[$j].”、“($filtKlic[($j)])。”]-”;
打印“[”($i+2)。,”。($k*$countFiltKlic)+$j)。“]-”;
打印“[”($l+$c)。”,“.$k.”]
“; $m=5;#只是随机数……我不想在测试期间得到无限循环 }否则{ 如果($m=5){ $l--; $c++; } $j++; } } } } } 我的@namestlpecklic; @nameStlpceKlic[0]=“日期”; 我的$o; 对于(我的$i=0;$i<$columnsCount-2;$i++){ foreach(@filklic){ 我的$o; $o++; @nameStlpceKlic[$o]=@filklic[($o-1)]。$i; } }
我有两个问题

  • 如何确保即使在某些日期缺少某些密钥,也能正常工作
  • 如何正确书写。我的代码太笨拙了

  • 这是我解决这类问题的一般方法

    在第二个表中,您按日期对数据进行分组,然后显示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
    }
    
    输出(为显示目的展开选项卡):


    我能够用“我惊动了外星人”的绝妙答案来编写代码。 第一件不同的事情是,我的数据以转置的方式格式化为数组数组

    $arr1 = [ '2013-12-22', '2013-12-22' ]; 
    $arr2 = [ 'Number1','Number2']; 
    $arr3 = [ '2328942', '679204']; 
    $arr4 = [ '1450398', '436713']; 
    
    此外,转换后的数据应保存在数组中。我已经写了这段代码。(这还远远不够完美,如果有任何进一步改进的建议,我很乐意听到。)

    ####################
    #转置数据
    my$datas=$args{DATA};
    my$headers=$args{headers};
    我的@rows=();
    我的@transposed=();
    对于我的$行(@$数据){
    对于我的$列(0..$#{$row}){
    push(@{$transposed[$column]},$row->[$column]);
    }
    }
    #################################
    我的@arr=@转置;
    #首先,定义标题。
    my$col_h=$args{HEADERS};
    我的$数据;
    我的$key_列表;
    foreach(@arr){
    我的%hash;
    #使用列标题数组作为键的哈希片
    #和数组作为值
    @哈希{@$col_h}=@$;
    #将此散列存储在按日期索引的数据散列中,然后按键索引
    $data->{$hash{date}}{$hash{key}}}=\%hash;
    #编译一个包含键的单独散列
    $key_list->{$hash{key}}++;
    }
    #制作一个键的排序列表,准备打印
    my@key\u list=排序键%$key\u list;
    #从列标题中删除前两个元素(“日期”和“键”)
    拼接(@$col_h,0,2);
    我的@output;
    我的@header;
    #打印出表格的标题行(我正在做一个简单的tab delim'd表格)
    #打印标准“日期\t”;
    推送(@header,“Date\t”);
    #对于数字1中的每个数字。。。数字
    每个我的$c(@$colu_h){
    #打印“密钥ID号”
    映射{push(@header,“$\u$c\t”)}@key\u列表;
    #映射{print STDERR“$\$c\t”}@key\u list;
    }
    #打印标准“
    ”; 推送(@输出,\@标题); 我的美元行; 我的$column; #现在打印出数据本身。按日期排序。。。 foreach my$date(排序键%$数据){ #打印STDERR“$date\t”; $row++; 我的@line; 推送(@line,“$date”); #对于每个数字1…数字 foreach my$header(@$col_h){ foreach my$key(@key\u list){ ##打印出值或-如果没有值 $column++; push(@line,($data->{$date}{$key}{$header}| |“-”)“\t”); #打印STDERR($data->{$date}{$key}{$header}| |“-”)“\t”; } } 打印STDERR“
    ”#表格行的末尾 $column=0; 推出
    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
    
    $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;
    
    }