DATA FILE temp.csv
1,2015-08-20,00:00:00,89,1007.48,295.551,296.66,
2,2015-08-20,03:00:00,85,1006.49,295.947,296.99,
3,2015-08-20,06:00:00,86,1006.05,295.05,296.02,
4,2015-08-20,09:00:00,85,1005.87,296.026,296.93,
5,2015-08-20,12:00:00,77,1004.96,298.034,298.87,
我想提取(column 6) value if (column 3 = 09:00:00)
推送到$result
变量。这需要是特定值/变量而不是数组。我需要使用该值进行其他计算并将其移动到数据库。这是我使用的代码,但我无法将特定值提取到变量。
my @temp_9 = map {
chomp;
my @t_fh_9 = split /,/;
sprintf "%.0f", $t_fh_9[6] if $t_fh_9[2] eq '09:00:00';
} <$ft1>;
当我试图减去或做其他数学时,这些数字是荒谬的。
答案 0 :(得分:1)
map
总是有一对一的映射,如果你输入10个东西,你将得到10个东西的列表。你想要的是一个有选择地推入数组的while循环。
use strict;
use warnings;
use v5.10;
my @nines;
while(<DATA>) {
chomp;
my @row = split /,/;
next unless $row[2] eq '09:00:00';
push @nines, sprintf("%.0f", $row[6]);
}
say join ", ", @nines;
__DATA__
1,2015-08-20,00:00:00,89,1007.48,295.551,296.66,
2,2015-08-20,03:00:00,85,1006.49,295.947,296.99,
3,2015-08-20,06:00:00,86,1006.05,295.05,296.02,
4,2015-08-20,09:00:00,85,1005.87,296.026,296.93,
5,2015-08-20,12:00:00,77,1004.96,298.034,298.87,
从您的变量名称@temp_9
和@t_fh_9
,我怀疑您在特定时间内对变量名称进行了硬编码。这将导致大量代码重复。相反,写一个小功能,花时间你正在寻找。
sub extract_column_for_time_of_day {
my($fh, $column_number, $time_of_day) = @_;
my @extracts;
while(<$fh>) {
chomp;
my @row = split /,/;
next unless $row[2] eq $time_of_day;
push @extracts, sprintf("%.0f", $row[$column_number]);
}
return @extracts;
}
say join ", ", extract_column_for_time_of_day(\*DATA, 6, '09:00:00');
最后,我猜你会在不同时间获取数据。这将导致一堆变量,这些变量作为一个整体难以传递。不是每次都有变量,而是将每个列表放入哈希值。
my $time = '09:00:00';
$extracts{$time} = [extract_column_for_time_of_day(\*DATA, 6, $time)];
答案 1 :(得分:1)
似乎混淆的一个原因是从数组中提取元素。数组是零个或多个标量元素 - 你不能只将一个元素分配给另一个元素,因为......好吧,如果不存在一个元素(通常情况下)会发生什么。
给定一个数组,我们可以:
pop @array
将返回最后一个元素(并将其从数组中删除),以便您my $result = pop @array;
[0]
是数组的第一个元素,因此我们可以my $result = $array[0];
my ( $result ) = @array;
- 因为在左侧我们现在有一个数组,它是一个单一元素 - @array
的第一个元素进入$result
。 (其余部分未在此方案中使用 - 但您可以执行my ( $result, @anything_else ) = @array;
因此,在您的示例中 - 如果您尝试执行的操作是检索符合条件的值,则该作业的常规工具将是grep
- 它通过应用条件测试来过滤数组每个元素。
所以:
#!/usr/bin/env perl
use strict;
use warnings;
my @lines = grep { (split /,/)[2] eq "12:00:00" } <DATA>;
print "@lines";
print $lines[0];
__DATA__
1,2015-08-20,00:00:00,89,1007.48,295.551,296.66,
2,2015-08-20,03:00:00,85,1006.49,295.947,296.99,
3,2015-08-20,06:00:00,86,1006.05,295.05,296.02,
4,2015-08-20,09:00:00,85,1005.87,296.026,296.93,
5,2015-08-20,12:00:00,77,1004.96,298.034,298.87
我们可以减少到:
my ( $firstresult ) = grep { (split /,/)[2] eq "12:00:00" } <DATA>;
print $firstresult;
但是因为我们想要转换我们的数组 - map
是工作的工具。
my ( $result ) = map { (split /,/)[6] - 273.15 } grep { (split /,/)[2] eq "12:00:00" } <DATA>;
print $result;
首先我们:
或者也许:
#!/usr/bin/env perl
use strict;
use warnings;
my ($result) = map {
( split /,/ )[2] eq "12:00:00"
? ( split /,/ )[6] - 273.15
: ()
} <DATA>;
print $result;
但就个人而言,我认为这有点复杂,可能很难理解。 map
是一个功能强大的功能,但可能会导致代码难以阅读以供将来的维护程序员使用。
所以我建议改为:
my $result;
while (<DATA>) {
my @fields = split /,/;
if ( $fields[2] eq "12:00:00" ) {
$result = $fields[6] - 273.15;
last;
}
}
print $result;
迭代您的数据,拆分 - 并测试 - 每一行,当您找到符合条件的行时,设置$result
并保释出循环。
答案 2 :(得分:0)
map
函数通常会返回一个列表,其中包含与源相同数量的元素,除非返回空元素或多元素列表。实际上,map
perl doc中的第一个示例之一显示了如何执行此操作,再次证明您应该首先检查文档。
my @temp_9 = map {
chomp;
my @t_fh_9 = split /,/;
$t_fh_9[2] eq '09:00:00' ? ( $t_fh_9[6] ) : ();
} <$ft1>;