【问题标题】:Perl function to find the longest word from each separate arrayPerl 函数从每个单独的数组中查找最长的单词
【发布时间】:2014-05-25 12:32:04
【问题描述】:

我有一个任务:

有几个数组,每个元素都是一个单词。创建一个函数,从每个给定数组中找到最长的单词并将结果作为列表返回。对数组的引用应作为参数传递给函数。

这个函数给了我两个数组中最长的单词。我只是不明白如何让它从每个单独的数组中找到最长的单词。

use strict;
my @arr1 = qw/one two three/;
my @arr2 = qw/four five seven/;
my $arr1 = \@arr1;
my $arr2 = \@arr2;
my @sorted_words;

sub func {
  for (@_) {
    for (@$_){
     @sorted_words = sort {length($b) <=> length ($a)} $_;}
  }
  print "The longest word is: $sorted_words[0]\n";
}
func($arr1, $arr2);

【问题讨论】:

  • 有没有哪一行你不明白,还是想让我们从头解释一下 Perl 语法? (OT:It's "Perl", not "PERL".
  • 在数组中查找最大、最长、最简单的值时,使用foreach 进行简单遍历比使用sort 更有效。

标签: arrays perl function word


【解决方案1】:

这个问题的答案已经在任何第一次介绍算法课程的第一讲的“嵌套循环”部分......

根据某个参数在数组中找到“最佳”值的基本算法是:

best ← worst possible value
for each value in array
    if value is better than best
        then best ← value
    end if
end for each

你想要的是最长的字符串,所以最坏的情况是一个空字符串。在 Perl 中,这会给你:

my @array = qw/one two three/;
my $best = '';
for my $value (@array) {
    if (length $value > length $best) {
        $best = $value;
    }
}

如果您想对多个数组执行此操作,只需添加一个额外的外循环:

best_array ← ()
for each array in array_of_array
    best ← worst possible value
    for each value in array
        if value is better than best
            then best ← value
        end if
    end for each
    best_array ← best_array, best
end for each

或者,在 Perl 中:

my @arr1 = qw/one two three/;
my @arr2 = qw/four five seven/;
my @arr3 = qw/six eight nine/;
my @array_of_arrays = (\@arr1, \@arr2, \@arr3);
my @longest_words;

for my $array (@array_of_arrays) {
    my $best = '';
    for my $value (@$array) {   # notice "@$" to dereference the array
        if (length $value > length $best) {
            $best = $value;
        }
    }
    push @longest_words, $best;
}

更新:子程序

我刚刚意识到这个问题专门要求一个子程序。上面的代码很容易变成子程序:

my @arr1 = qw/one two three/;
my @arr2 = qw/four five seven/;
my @arr3 = qw/six eight nine/;
my @array_of_arrays = (\@arr1, \@arr2, \@arr3);

sub funct {
    my @longest_words;
    for my $array (@_) {
        my $best = '';
        for my $value (@$array) {   # notice "@$" to dereference the array
            if (length $value > length $best) {
                $best = $value;
            }
        }
        push @longest_words, $best;
    }
    return @longest_words;
}

my @longest_words = funct(@array_of_arrays);

【讨论】:

    【解决方案2】:

    问题要求您提供一个“将结果作为列表返回”的函数,因此在函数内打印答案不是答案。

    您需要一个一个地处理数组,并记录到目前为止您找到的所有最长的单词,然后在最后将它们全部返回。

    这样的东西很好用:

    use strict;
    use warnings;
    
    my @arr1 = qw/one two three/;
    my @arr2 = qw/four five seven/;
    
    sub func {
      my @max;
      for my $list (@_) {
        my @sorted = sort { length($b) <=> length ($a) } @$list;
        push @max, $sorted[0];
      }
      @max;
    }
    
    my @longest = func(\@arr1, \@arr2);
    printf "The longest words are: %s\n", join ', ', @longest;
    

    输出

    The longest words are: three, seven
    

    但我会编写一个子程序,从 one 数组中返回最长的单词,然后使用map 创建所有最长单词的列表。

    应该是这样的

    use strict;
    use warnings;
    
    my @arr1 = qw/one two three/;
    my @arr2 = qw/four five seven/;
    
    sub longest {
      my ($list) = @_;
      my $longest = '';
      for (@$list) {
        $longest = $_ if length > length($longest);
      }
      $longest;
    }
    
    sub func {
      map longest($_), @_;
    }
    
    my @longest = func(\@arr1, \@arr2);
    printf "The longest words are: %s\n", join ', ', @longest;
    

    【讨论】:

      【解决方案3】:

      另一种解决方案是使用数组或数组数组调用函数。如果使用后者调用,只需递归调用该函数即可获取值。

      下面会这样做并使用List::Util reduce 来确定最大length 元素。

      use strict;
      use warnings;
      
      use List::Util qw(reduce);
      
      my @AoA = (
          [qw(one two three)],
          [qw(four five seven)],
          [qw(six eight nine)],
      );
      
      sub longest {
          return map {longest(@$_)} @_ if ref $_[0];
          return reduce {length $b > length $a ? $b : $a} @_;
      }
      
      my @longest_words = longest(@AoA);
      print "@longest_words\n";
      

      输出:

      three seven eight
      

      【讨论】:

      • +1 for reduce,但恕我直言,使用两个子例程而不是一个带有递归的子例程会更具可读性,也更快。
      • TY。如果我没有发现处理 AoA 的要求是人为的,我会同意。事实上,我只是认为这是一种有用的技术来演示,以及使用reduce
      【解决方案4】:

      如果你单独调用每个数组的子程序,它会按照你想要的方式工作。

      使用

      func($arr1);
      func($arr2);
      

      代替:

      func($arr1, $arr2);
      

      顺便说一句,您现在应该知道该子例程仅适用于一个数组。尝试通过将 @arr1 重命名为 @arr2 并将 @arr2 重命名为 @arr1 来更改您的数组名称,然后运行您的原始程序。

      【讨论】:

      • 有人能告诉我为什么我被否决了吗?我真的不明白。
      • 问题是“创建一个函数,从每个给定数组中找到最长的单词并将结果作为列表返回”。你没有指定你的子程序func,但是你没有保存它的返回值,并且调用它两次不会让它返回一个列表
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 2018-12-13
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 2018-09-28
      相关资源
      最近更新 更多