我试图获得A,B和C列的最高值,并将这些值与它们出现的日期和时间联系起来。要获得最大值,我只需要使用List :: Util模块,但我不知道如何将其指向数组中的特定列,然后引用日期和时间。
DATE TIME A B C
11/22/14 21:00:00 5,854 2,105 1,290
11/22/14 21:02:35 7,692 2,593 2,649
11/22/14 21:05:10 1,639 458 444
11/22/14 21:07:00 1,032 487 434
11/22/14 21:08:15 4,707 1,352 646
11/22/14 21:10:22 351 46 162
11/22/14 21:10:55 5,507 1,943 957
11/22/14 21:11:00 1,703 647 516
11/22/14 21:12:00 2,359 751 785
11/22/14 21:14:05 67 25 44
11/22/14 21:16:25 4,072 1,596 1,050
11/22/14 21:17:48 5,060 2,131 1,996
11/22/14 21:19:00 341 42 137
11/22/14 21:23:00 1,308 71 634
答案 0 :(得分:1)
这可能类似于Schwartzian变换,以减少线路分裂造成的一些开销,并使用reduce()
核心模块中的List::Util
来选择一条具有最大值的线,
use strict;
use warnings;
use List::Util 'reduce';
(undef, my @tmp) = map { tr/,/./; [ $_, split ] } <DATA>;
my ($max_a) =
map $_->[0],
reduce {
$a->[3] > $b->[3] ? $a : $b
}
@tmp;
my ($max_b) =
map $_->[0],
reduce {
$a->[4] > $b->[4] ? $a : $b
}
@tmp;
my ($max_c) =
map $_->[0],
reduce {
$a->[5] > $b->[5] ? $a : $b
}
@tmp;
print
"maxA: ", $max_a,
"maxB: ", $max_b,
"maxC: ", $max_c;
__DATA__
DATE TIME A B C
11/22/14 21:00:00 5,854 2,105 1,290
11/22/14 21:02:35 7,692 2,593 2,649
11/22/14 21:05:10 1,639 458 444
11/22/14 21:07:00 1,032 487 434
11/22/14 21:08:15 4,707 1,352 646
11/22/14 21:10:22 351 46 162
11/22/14 21:10:55 5,507 1,943 957
11/22/14 21:11:00 1,703 647 516
11/22/14 21:12:00 2,359 751 785
11/22/14 21:14:05 67 25 44
11/22/14 21:16:25 4,072 1,596 1,050
11/22/14 21:17:48 5,060 2,131 1,996
11/22/14 21:19:00 341 42 137
11/22/14 21:23:00 1,308 71 634
输出
maxA: 11/22/14 21:10:22 351 46 162
maxB: 11/22/14 21:12:00 2.359 751 785
maxC: 11/22/14 21:10:55 5.507 1.943 957
一些重构,
sub get_max {
my ($pos, $r) = @_;
return map $_->[0],
reduce {
$a->[$pos] > $b->[$pos] ? $a : $b
}
@$r;
}
my ($max_a) = get_max(3, \@tmp);
my ($max_b) = get_max(4, \@tmp);
my ($max_c) = get_max(5, \@tmp);
答案 1 :(得分:1)
我的理解:
最后你想要三个数据:
您不想对数据进行排序。您无需存储任何其他内容。
你没有指定任何代码,所以我不打算给你一个完整的程序。你需要自己尝试一下。相反,我会给你一些提示:
您应该阅读References以及它们的工作原理。我们会将您的数据存储在参考文献中:
my %data;
$data{A}->{time} = "xxxxx"; # Time of highest item in column "A"
$data{A}->{date} = "xxxxx"; # Date of highest item in column "A"
$data{A}->{value} = "xxxx"; # Value of highest item in column "A"
与其他两列相同。
你可以遍历你的数据(它是一个文件吗?你没有解释)
my %data;
while ( my $line .... ) {
my ( $date, $time, a_value, b_value, c_value ) = split /\s*/, $line;
if ( not exists $data{A}->{value} or $a_value > $data{A}->{value} ) {
$data{A}->{value} = $a_value;
$data{A}->{date} = $date;
$data{A}->{time} = $time;
}
... # Same for B and C
在这个循环中,如果该值高于我之前存储的值,我将$data{A}->{value
}设置为我刚刚读入的值。这是寻找最高价值的常用方式。如果该值尚不存在,我还需要存储它。因此,我检查是否存在$data{A}->{value}
。如果没有,我还是需要存储该值。 (我本可以做if ( not exists $data{A} or $a_value > $data{A}->{value} )
)。
在while循环之后,%data
将包含每列的最高值以及这些值的日期和时间。有很多代码重复。我本可以为每一列添加一个内部循环,但只用三列就不值得。
另外,请记住不要在数据中包含标题列。
如果$data{A}->{value}
让您感到困惑,可以使用三个单独的哈希值:一个用于存储日期,一个用于存储时间,另一个用于存储值。
my %times;
my %dates
my %values;
while ( my $line .... ) {
my ( $date, $time, a_value, b_value, c_value ) = split /\s*/, $line;
if ( not exists $values{A} or $a_value > $values{A} ) {
$values{A} = $a_value;
$dates{A} = $date;
$times{A} = $time;
}
... # Same for B and C
答案 2 :(得分:1)
这是一种机械的,程序性的,比“婴儿perl”方法更先进。该剧本非常简单,并且坚持使用已知的perl“习语”。
首先,我们使用DATA
将所有@lines
放入map
- 一个数组数组 - 我们可以在这里使用while (<DATA>){...}
循环。我们在此时删除逗号(tr/,//d
)
然后我们使用每列临时数组(@atmp
,@btmp
,...)并使用sort
@lines
直接填充它们,访问$a->[n] ...
操作的内部匿名数组(sort
)中的相关列:这样我们就不使用模块并避免使用map
。
一旦我们按列(反向)对数组进行排序,我们就可以打印第一个元素以获得每列的最高值。要打印,我们 dereference 第一个元素(例如 @{$atmp[0]}
因为它是一个匿名数组)才能回来整条线 - 这样我们就将“最高价值”与其他列保持在一起。
NB 突出显示柱状排序我更改了原始数据,以便不同的行显示为每列的最大值。在原始数据中,第二行具有所有三列的最高值。我只使用tr|,||d
代替tr/,//d
来破坏SO语法高亮显示。
use v5.16; # adds strict and warnings
my @lines = map { tr|,||d; [ split ] } <DATA> ;
shift @lines; # removes header
my @atmp = sort{ $b->[2]<=>$a->[2] } @lines;
my @btmp = sort{ $b->[3]<=>$a->[3] } @lines;
my @ctmp = sort{ $b->[4]<=>$a->[4] } @lines ;
print "\t DATE TIME A B C \n";
print "Max A: @{$atmp[0]}\nMax B: @{$btmp[0]}\nMax C: @{$ctmp[0]}\n" ;
__DATA__
DATE TIME A B C
11/22/14 21:00:00 5,854 2,105 1,290
11/22/14 21:02:35 7,692 2,593 2,649
11/22/14 21:05:10 1,639 458 444
11/22/14 21:07:00 1,032 487 434
11/22/14 21:08:15 4,707 1,352 6460
11/22/14 21:10:22 351 46 162
11/22/14 21:10:55 5,507 9,943 957
11/22/14 21:11:00 1,703 647 516
11/22/14 21:12:00 2,359 751 785
11/22/14 21:14:05 67 25 44
11/22/14 21:16:25 4,072 1,596 1,050
11/22/14 21:17:48 5,060 2,131 1,996
11/22/14 21:19:00 341 42 137
11/22/14 21:23:00 1,308 71 634
<强>输出强>:
~/$ perl sort_by_column.pl
DATE TIME A B C
Max A: 11/22/14 21:02:35 7692 2593 2649
Max B: 11/22/14 21:10:55 5507 9943 957
Max C: 11/22/14 21:08:15 4707 1352 6460
use DDP;
后跟p @lines
,p @atmp
等创建的数据结构,可以成为“可视化”的有用工具。有关详细信息,请参阅Data::Printer
。