It seems one of the sources of confusion is extracting an element from an array. An array is zero or more scalar elements - you can't just assign one to the other, because .... well, what should happen if there isn't just one element (which is the usual case).
Given an array, we can:
pop @array will return the last element (and remove it from the array) so you could my $result = pop @array;
[0] is the first element of the array, so we can my $result = $array[0];
- Or we can assign one array to another:
my ( $result ) = @array; - because on the left hand side we have an array now, and it's a single element - the first element of @array goes into $result. (The rest isn't used in this scenario - but you could do my ( $result, @anything_else ) = @array;
So in your example - if what you're trying to do is retrieve a value matching a criteria - the normal tool for the job would be grep - which filters an array by applying a conditional test to each element.
So:
#!/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
Which we can reduce to:
my ( $firstresult ) = grep { (split /,/)[2] eq "12:00:00" } <DATA>;
print $firstresult;
But as we want to want to transform our array - map is the tool for the job.
my ( $result ) = map { (split /,/)[6] - 273.15 } grep { (split /,/)[2] eq "12:00:00" } <DATA>;
print $result;
First we:
- use grep to extract the matching elements. (one in this case, but doesn't necessarily have to be!)
- use map to transform the list, so that that we turn each element into just it's 6th field, and subtract 273.15
- assign the whole lot to a list containing a single element - in effect just taking the first result, and throwing the rest away.
Or perhaps:
#!/usr/bin/env perl
use strict;
use warnings;
my ($result) = map {
( split /,/ )[2] eq "12:00:00"
? ( split /,/ )[6] - 273.15
: ()
} <DATA>;
print $result;
But personally, I think that's getting a bit complicated and may be hard to understand. map is a powerful function, but can lead to code that's hard to read for future maintenance programmers.
So I would suggest instead:
my $result;
while (<DATA>) {
my @fields = split /,/;
if ( $fields[2] eq "12:00:00" ) {
$result = $fields[6] - 273.15;
last;
}
}
print $result;
Iterate your data, split - and test - each line, and when you find one that matches the criteria - set $result and bail out of the loop.
9:00:00-- is the missing leading zero an error in your paste or your code?mapwhen you want togrep.grepis fine when you want to filter a list, but when you want to filter and transform it's not appropriate. Especially if the filter and transform have to do the same data processing (split the CSV line).map, grep, map. Firstmapparses the line, thengrepfilters for the lines in question, and secondmapextracts just the desired column. At that point a while loop is simpler.