Perl中的变换/枢轴数组 [英] Transform/pivot array in perl

查看:45
本文介绍了Perl中的变换/枢轴数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚持写Perl代码来转换2d数组.

Im stuck writing Perl code which transforms 2d array.

  • 数组的第一列始终是日期
  • 数组的第二列是排序的键.
  • 数据位于数组数据"中,并按日期和键顺序排序.

  • First column of the array is always date
  • Second column of the array is key that sorts.
  • Data is located in array "data" and is ordered by date and then key.

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

My situation should be understandable from the tables under. Unique values from the second column will be selected and later divided into columns header (green table)

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

It should work with and number of columns or dates/keys.

之前的结构

之后的结构

我的代码:

#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;
    }
}

我有2个问题.

  1. 即使某些密钥在某些日期丢失,如何确保它也能正常工作.
  2. 如何正确编写.我的代码太笨拙了.

推荐答案

这是我解决此类问题的通用方法.

Here is my general approach for solving this kind of problem.

在第二个表中,将数据按日期分组,然后显示number1的值和number2的值.这应该给您一些提示,告诉您如何组织数据结构以及需要为打印编制索引的内容.

In the second table, you're grouping your data by the date, then displaying the values for number1 and the values for number2. This should give you a hint as to how you want to organise your data structure and what you need to index for printing.

(我假设)您当前的数据存储在一个数组数组中.我懒得复制值,所以我用补偿值制作了自己的AoA.我在代码中添加了注释,以便您了解我的工作方式.

Your current data is (I assume) stored in an array of arrays. I was too lazy to copy the values, so I made my own AoA with made up values. I've sprinkled comments through the code so you can see how I worked on this.

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
}

输出(带有用于显示目的的选项卡扩展):

Output (with tabs expanded for display purposes):

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

这篇关于Perl中的变换/枢轴数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆