【问题标题】:Creating a lazy hashed iterator创建一个惰性散列迭代器
【发布时间】:2013-12-06 02:22:45
【问题描述】:

在研究这个问题时,我查看了《高阶 Perl》一书中的迭代器章节,其中的一些材料让我有点不知所措,并认为不一定能解决我在这里特别想要的内容。

我所说的惰性散列迭代器是一种创建模拟这种行为的结构的方法:

%Ds = {
       '1' => 1 .. 20;
       '2' => 21 .. 40;
       '3' => 41 .. 60;
       '4' => 61 .. 80;
       ...
     }

不幸的是,由于这是一个散列,它不会按顺序排列,因此在数字非常大的情况下无用。

行为是这样的:

I have a number. 
I need to compare it with a sequence of ranges and as a result of the comparison the 
code/sub would return another number that is the "key" of that range in case the
number is in that range. (>= with the beginning or <= with the end point of said range)
The "key" of the ranges are numbers from 1..2..3 and so on.
The code/sub will always return for a positive integer no matter how large it is.

通过懒惰地实现这一切,我的意思是如果有一种方法可以模拟这种行为,而不是在每次调用 sub 或循环迭代时使用它们各自的“键”计算范围序列。基本上计算一次。

是的,我确实可以选择一个最大边界,在循环中对其进行硬编码并完成它,但问题是我不知道我最终需要多少这些步骤。

有没有办法使用 perl 结构来做到这一点,或者也许有一个提供这种行为的 CPAN 模块,但我对它的简单搜索并没有发现它。

这里有一段代码说明了我的意思:

sub get_nr {
  my $nr = shift;
  my %ds = map {  $a = '1' if /1/ .. /20/;
                  $a = '2' if /21/ .. /40/;
                  $a = '3' if /41/ .. /60/;
                  $a = '4' if /61/ .. /80/;
                  $_ => $a } 1 .. 80;

  while (my ($k, $v) = each %ds) {
     if ( $k == $nr){
     print "number is in range $v \n";
     }
  }
}

输出:

 get_nr(4);
 get_nr(15);
 get_nr(22);
 get_nr(45);

是:

number is in range 1
number is in range 1
number is in range 2
number is in range 3

【问题讨论】:

  • 我很难理解你的问题,因为你一直认为想要一种行为,但你没有描述任何行为。 (您似乎描述了一种数据结构。)我是否正确地说您想要一个名为 $h{$x} 并返回 $x*20-19 .. $x*20 的函数?
  • 另外,这是一个听起来像 XY 问题的典型问题:询问有关解决方案的问题,而不是您要解决的问题。了解您尝试使用此技术解决什么问题会很有帮助。
  • 好的,我现在明白你的问题了。您说您可以通过困难的方式轻松解决此问题,但您正在寻找一种懒惰的方式。那你是什么意思?我可以用几种不同的方式解决这个问题,但我不知道你已经尝试过什么并且认为微不足道。顺便说一句,如果您想查找数字,您的哈希值是向后的:%ds = (1 =&gt; 'x', 2 =&gt; 'x'...)
  • 是的......很遗憾,这里没有办法给你建议。你是说:“我想要一些 Perl 代码,当我给它一个数字时,它会给我一个键。我希望它能够处理任何数字。”您将需要比这更具体很多。您所描述的是一个基于一些数学公式的子例程,但这意味着我能给出的最佳建议是将您指向perldoc perlsub 并可能指向perlop 以获取要使用的运算符列表。
  • 你刚才又说了同样的话,用更详细的方式。让我举个例子:sub inrange { my $num = shift; my $dec = int($num / 100); my $min = $dec * 100; my $max = ($dec + 1) * 100; print "$num is between $min and $max"; } 这将在数学上计算数字在 100 的哪个范围内。

标签: perl functional-programming cpan


【解决方案1】:

根据 cmets 中的讨论,您想要的代码似乎是一个非常简单的子程序

sub get_nr {
    my $nr = shift;
    my $range = int(($nr-1) / 20) + 1;
    return $range;
}

您需要补偿边缘情况,例如,您希望 20 返回 1,因此我们需要在除数之前从数字中减去 1。

如果您想进一步自定义,您可以使用变量作为范围大小,而不是硬编码数字。

【讨论】:

  • 请同时添加我以错误方式查看问题的 cmets,不需要任何功能等...还将子名称更改为 get_range。
  • range 必须是硬编码的,我在 OP 中给出的示例建议这样做。
  • @user3046061 在您的思维方式中,您自己似乎有点硬编码。 :-) 如果这解决了您的问题,您应该考虑接受答案。
  • 这对于那些偶然发现这一点并且实际上需要其他东西的人来说会更有用。
  • @user3046061 我相信即使没有我详细说明我们讨论的每个细节,人们也能确定这段代码是否对他们有用。
【解决方案2】:
sub get_range_number {
   my ($n) = @_;
   return int(($n-1)/20) + 1;
}

print "$_ is in range ".get_range_number($_)."\n"
   for 4, 15, 22, 45;

【讨论】:

  • PS - 注意打印是如何在函数之外完成的。打印与确定范围数无关。
猜你喜欢
  • 2011-01-16
  • 2013-11-28
  • 1970-01-01
  • 2016-07-24
  • 2021-10-15
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多