2013-09-26 104 views
1

我不断学习哈希和你可以用它们做的各种事情。 taday我有这个问题。如何按值排序散列,当我有2个键时?我如何打印出来? 我有一个csv文件。即时尝试将值存储在散列中,按值排序。这样我就可以打印出最大和最小的值,我还需要这个值在那里的日期。 到目前为止,我可以打印散列,但我不能排序它。按价值排序2键哈希

#!/usr/bin/perl 
#find openMin and openMax. 
use warnings; 
use strict; 

my %pick; 
my $key1; 
my $key2; 
my $value; 
my $file= 'msft2.csv';    
my $lines = 0; 
my $date; 
my $mm; 
my $mOld = ""; 

my $open; 
my $openMin; 
my $openMax; 
open (my $fh,'<', $file) or die "Couldnt open the $file:$!\n"; 
while (my $line=<$fh>) 
{ 
    my @columns = split(',',$line); 
    $date = $columns[0]; 
    $open = $columns[1]; 

    $mm = substr ($date,5,2); 

    if ($lines>=1) {      #first line of file are names of columns  wich i 
    $key1 = $date;       #dont need. data itself begins with second line 
    $key2 = "open"; 
    $value = $open; 
    $pick{$key1}{"open"}=$value; 


    } 
$lines++; 
} 
foreach $key1 (sort keys %pick) { 
foreach $key2 (keys %{$pick{$key1}}) { 
    $value = $pick{$key1}{$key2}; 
    print "$key1 $key2 $value \n"; 

} 
} 
exit; 

回答

3

1.使用一个真正的CSV解析器

解析CSV与split /,/优良工程......除非其中一个字段包含逗号。如果你是绝对肯定的,100%确信你的代码永远不会需要在其中一个字段中用逗号分析CSV,所以可以自由地忽略这一点。如果没有,我建议使用Text::CSV。用法示例:

use Text::CSV; 

my $csv = Text::CSV->new({ binary => 1 }) 
    or die "Cannot use CSV: " . Text::CSV->error_diag(); 

open my $fh, "<", $file or die "Failed to open $file: $!"; 
while (my $line = $csv->getline($fh)) { 
    print @$line, "\n"; 
} 
$csv->eof or $csv->error_diag(); 
close $fh; 

2.排序

我只看到你的哈希一个辅助键:open。如果你正在尝试的基础上open值进行排序,做这样的事情:

my %hash = (
    foo => { open => "date1" }, 
    bar => { open => "date2" }, 
); 

foreach my $key (sort { $hash{$a}{open} cmp $hash{$b}{open} } keys %hash) { 
    print "$key $hash{$key}{open}\n"; 
} 

(假定你排序值不是数字如果值是数字(比如3-17.57 )使用飞船操作<=>不是字符串比较操作cmp的见perldoc -f sort的细节和例子)

编辑:。你没有解释你的日期是什么格式,如果他们都在YYYY-MM-DD格式,排序。如上所述,但如果他们在MM-DD-YYYY格式,例如,01-01-2014会在12-01-2013之前出现。处理这个问题的最简单方法是,将日期的组成部分从最重要的到最不重要的(即一年后接着一个月,接着一天)重新排序。你可以使用这个Time::Piece像这样:

use Time::Piece; 

my $date = "09-26-2013"; 
my $t = Time::Piece->strptime($date, "%m-%d-%Y"); 
print $t->strftime("%Y-%m-%d"); 

另一珍闻:一般你使用他们的权利之前,你应该只声明变量。声明程序顶部的所有内容除了降低可读性外,不会获得任何收益。

0

你可以串连键1和键2到单个键:

$key = "$key1 key2"; 
$pick{$key} = $value; 
+0

其可能性很大。但为了学习清酒编号喜欢知道如何按值排序2键的散列。 – AndreiMotinga

+0

没有“排序哈希”或“排序两个关键哈希”。基于某种比较功能,它总是“排序”。 –