2013-09-26 101 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

沒有「排序哈希」或「排序兩個關鍵哈希」。基於某種比較功能,它總是「排序」。 –