【问题标题】:How to print the previous Key Value in Perl?如何在 Perl 中打印上一个键值?
【发布时间】:2021-02-16 20:57:43
【问题描述】:

在这段代码中,我正在检查某个键是否存在。 在这里,我正在检查键“Uri”是否存在。我的输出为“3”。

use strict; 
use warnings;

my %Names = ( 
    Martha  =>2, 
    Vivek   =>9, 
    Jason   =>6, 
    Socrates=>7, 
    Uri     =>3, 
    Nitin   =>1, 
    Plato   =>0, 
); 

if (exists $Names{Uri} ) {
    print "$Names{Uri}\n";
}
foreach my $name (sort {$Names{$a} cmp $Names{$b}} keys %Names) 
{ 
    print $name, $Names{$name}."\n";
} 

输出

3
Plato    0
Nitin    1
Martha   2
Uri      3
Jason    6
Socrates 7
Vivek    9

但是,我希望之前的键值出现在该键之前。例如:

  1. 如果我搜索键“Uri”输出应该是“2”
  2. 如果我搜索键“Vivek”输出应该是“7”
  3. 如果我搜索键“Plato”输出应该是“0”

有人知道怎么做吗?

【问题讨论】:

  • 你能定义“以前的值”吗?您的意思是哈希中的最大值小于您要查找的值吗? (在这种情况下,请参阅@toolic 的答案)或其他?

标签: perl perl-hash


【解决方案1】:

创建一个散列 values 的排序数组,然后搜索该数组以获取刚好低于搜索键值的值。

use strict; 
use warnings;

my %Names = ( 
    Martha  =>2, 
    Vivek   =>9, 
    Jason   =>6, 
    Socrates=>7, 
    Uri     =>3, 
    Nitin   =>1, 
    Plato   =>0, 
); 

my @vals = sort {$a <=> $b} values %Names;

get_prev('Uri');
get_prev('Vivek');
get_prev('Plato');

sub get_prev {
    my $k = shift;
    if (exists $Names{$k}) {
        for (@vals) {
            if ($Names{$k} == $vals[$_]) {
                my $idx = ($_ == 0) ? 0 : $_ - 1;
                print $vals[$idx], "\n";
                last;
            }
        }
    }
}

打印:

2
7
0

【讨论】:

    【解决方案2】:

    如果您想全部打印:

    my $prev;
    for my $name (
       sort { $Names{$a} <=> $Names{$b} }    # Note to use of <=> for numerical comparisons.
          keys(%Names)
    ) {
       say "$name $Names{$prev}" if $prev;
       $prev = $name;
    } 
    

    同样,只打印一个

    my $find = 'Uri';
    
    my $prev;
    for my $name (
       sort { $Names{$a} <=> $Names{$b} }
          keys(%Names)
    ) {
       if ($name eq $find) {
          say "$name $Names{$prev}" if $prev;
          last;
       }
    
       $prev = $name;
    }
    

    上面的帽子是一种执行多次查找的昂贵方式。 为此,我们将构建从名称到以前名称的映射。

    my %prev_name_lkup;
    my $prev;
    for my $name (
       sort { $Names{$a} <=> $Names{$b} }
          keys(%Names)
    ) {
       $prev_name_lkup{$name} = $prev if $prev;
       $prev = $name;
    } 
    

    这也可以这样做:

    my @sorted_names =
       sort { $Names{$a} <=> $Names{$b} }
          keys(%Names);
    
    my %prev_name_lkup =
       map { $sorted_names[$_-1] => $sorted_names[$_] }
          1..$#sorted_names;
    

    无论哪种方式,查找都将如下所示:

    say "Uri $Names{$prev_name_lkup{Uri}}";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-07
      • 2012-09-20
      • 2022-12-14
      • 2014-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多