根据值对深层嵌套哈希的键进行排序?

时间:2017-03-25 23:36:56

标签: perl

尝试根据其值来排序嵌套哈希,长篇大论,我解析app并将某些值存储在%senseHash哈希中 之后,我想循环排序%rankedTest并输出到文件 我的代码:

%rankedTest

但输出如下:

foreach my $str (keys %senseHash)
{
    my $selectedSense;
    if (exists $senseHash{$str}{'phone'} && exists $senseHash{$str}{'product'})
     {
        if ($senseHash{$str}{'phone'} > $senseHash{$str}{'product'})
        {
            $selectedSense='phone';
        }else
        {
            $selectedSense='product';
        }
         my $pPhone = $senseHash{$str}{'phone'} / $senses{'phone'};
         my $pProduct = $senseHash{$str}{'product'} / $senses{'product'};
         my $rankScore = abs(log($pPhone/$pProduct));
         $rankedTest{$str}{$selectedSense}=$rankScore;
     }
}
open($f1, '>', $inputs[1]);
foreach my $e (keys  %rankedTest)
{
    foreach my $s (sort { $rankedTest{$e}{$b} <=> $rankedTest{$e}{$a} } keys %{$rankedTest{$e}})
    {
        print $f2 "feature:$e -> sense:$s -> score:$rankedTest{$e}{$s} \n";
    }
} 

虽然我真正想要的是:

feature:operations -> sense:product -> score:0.0859904478555225 
feature:move -> sense:product -> score:0.309133999169732 
feature:dispute -> sense:phone -> score:0.0963311089384321 

任何线索我做错了什么或我怎么做到这一点。任何建议都会有所帮助。

编辑:内部哈希有一个密钥,可以是电话或产品,我想根据这个密钥值排序,无论密钥是feature:move -> sense:product -> score:0.309133999169732 feature:dispute -> sense:phone -> score:0.0963311089384321 feature:operations -> sense:product -> score:0.0859904478555225 还是phone

2 个答案:

答案 0 :(得分:2)

基本上,您正在排序错误哈希的元素。您的数据结构%rankedTest如下所示

my %rankedTest = (
    operations => { product => 0.0859904478555225 },
    move       => { product => 0.309133999169732 },
    dispute    => { product => 0.0963311089384321 },
);

并且您正在排序看起来像{ product => 0.0859904478555225 }的内部哈希的键。但是每个元素中只有一个元素,所以你的内部for循环只执行一次而排序没有区别

这里我用外部哈希的product元素的值对外部哈希进行了排序

请注意,在处理复杂数据结构时,将中间结果保存到临时变量中通常更简单。在这里,我将已排序的键存储在数组@features中,并将得分的值存储在$score中,以便将长哈希表达式保存到print语句中

my @features = sort {
    $rankedTest{$b}{product} <=> $rankedTest{$a}{product}
} keys %rankedTest;

for my $feature ( @features ) {

    my $score = $rankedTest{$feature}{product};

    print "feature:$feature -> sense:product -> score:$score\n";
}

输出

feature:move -> sense:product -> score:0.309133999169732
feature:dispute -> sense:product -> score:0.0963311089384321
feature:operations -> sense:product -> score:0.0859904478555225

答案 1 :(得分:1)

要按底层中的值对多级哈希进行排序,我们必须比较所有条目。

此代码使用(double)map构建要为所有级别打印的字符串,然后对其进行排序

use warnings;
use strict;
use feature 'say';

# Example hash     
my %h = ( 
    oper => { prod => 0.8, phone => 0.03 },  
    disp => { prod => 0.2, phone => 0.05 },  
    move => { prod => 0.6, phone => 0.01 } 
); 

my @res = 
    sort { (split ":", $b)[-1] <=> (split ":", $a)[-1] }
    map { 
        my $k = $_; 
        map { "feature:$k -> sense:$_ -> score:$h{$k}{$_}" }
        keys %{$h{$k}} 
    }   
    keys %h; 

say for @res;

输出

feature:oper -> sense:prod -> score:0.8
feature:move -> sense:prod -> score:0.6
feature:disp -> sense:prod -> score:0.2
feature:disp -> sense:phone -> score:0.05
feature:oper -> sense:phone -> score:0.03
feature:move -> sense:phone -> score:0.01

我将phone值设置为小于prod以模仿发布的数据(与处理无关)。

示例哈希%h代表问题中的%rankedTest。它可能在子索引中具有prodphone之一或两者(或没有)。