【问题标题】:How to count the odd number of occurrences in Perl?如何计算 Perl 中出现的奇数次?
【发布时间】:2020-12-21 14:48:50
【问题描述】:

我有一个 Perl 程序,它应该计算元素在数组中出现的次数,如果出现的次数是奇数,则打印出元素的值。

这是我的代码。

#!/usr/bin/perl
use strict;
use warnings;

sub FindOddCount($)
{
    my @arraynumber = @_; 
    my $Even = 0;
    my $i = 0;
    my $j = 0;
    my $array_length = scalar(@_);
    for ($i = 0; $i <= $array_length; $i++)
    {   
        my $IntCount = 0;
        for ($j = 0; $j <= $array_length; $j++)
        {
            if ($arraynumber[$i] == $arraynumber[$j])
            {
                $IntCount++;
                print($j);
            }
        }
        $Even = $IntCount % 2;
        if ($Even != 0)
        {
            return $arraynumber[$i];
        }
    }   
    if ($Even == 0)
    {   
        return "none";
    }   
}

my @array1 = (1,1,2,2,3,3,4,4,5,5,6,7,7,7,7);
my @array2 = (10,10,7,7,6,6,2,2,3,3,4,4,5,5,6,7,7,7,7,10,10);
my @array3 = (6,6,10,7,7,6,6,2,2,3,3,4,4,5,5,6,7,7,7,7,10.10);
my @array4 = (10,10,7,7,2,2,3,3,4,4,5,5,7,7,7,7,10,10,6);
my @array5 = (6,6);
my @array6 = (1);

my $return_value1 = FindOddCount(@array1);
my $return_value2 = FindOddCount(@array2);
my $return_value3 = FindOddCount(@array3);
my $return_value4 = FindOddCount(@array4);
my $return_value5 = FindOddCount(@array5);
my $return_value6 = FindOddCount(@array6);

print "The Odd value for the first array is $return_value1\n";
print "The Odd value for the 2nd array is $return_value2\n ";
print "The Odd value for the 3rd array is $return_value3\n ";
print "The Odd value for the 4th array is $return_value4\n ";
print "The Odd value for the 5th array is $return_value5\n ";
print "The Odd value for the sixth array is $return_value6\n ";

这是我的结果。

第一个数组的奇数值是 15 第一个数组的奇数值是 21 第一个数组的奇数值是 21 第一个数组的奇数值是 19 第一个数组的奇数值是 2 第一个数组的奇数值是 1

如果你不能说。它正在打印数组中所有元素的计数,而不是返回出现奇数次的元素。另外我得到这个错误。

在 OddCount.pl 第 17 行的数字 eq (==) 中使用未初始化的值。

第 17 行是比较第一个数组和第二个数组的地方。然而,这些值被清楚地实例化了,当我打印出来时它们就起作用了。有什么问题?

【问题讨论】:

  • 请修正你的缩进,它几乎无法阅读。

标签: perl ubuntu


【解决方案1】:

为一个数组构建一个频率散列,然后通过它查看哪些元素具有奇数

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

my @ary = qw(7 o1 7 o2 o1 z z o1);  # o1,o2  appear odd number of times

my %freq;
++$freq{$_} for @ary;

foreach my $key (sort keys %freq) { 
    say "$key => $freq{$key}" if $freq{$key} & 1;
}

比问题中的代码简单——但也很容易修复。见下文。

一些笔记

  • ++$freq{$_} 将哈希 %freq 中的键 $_ 的值增加 1,或者如果它不存在,则将键添加到哈希中(通过 autovivification)和将其值设置为 1。因此,当最后使用此代码迭代数组时,哈希 %freq 包含数组元素的键和元素的值的计数

  • 测试$n &amp; 1 使用bitwise AND -- 如果$n 设置了最低位,则为真,所以如果它是奇数

  • ++$freq{$_} for @ary; 是一个Statement Modifier,为@ary 的每个元素运行语句,其中当前元素的别名是$_ 变量

打印出来

o1 => 3 o2 => 1

这种奇数频率元素(如果有)的打印是按元素中的字母顺序排序的,就是这样。请更改为可能需要的任何特定顺序,或让我知道。


对问题中的代码的评论,通过两个简单的修复是正确的。

  • 它在sub FindOddCount($) 中以错误的方式使用prototypes。我怀疑这不是必需的,所以我们不要纠缠于此 - 只需放弃它并使其成为 sub FindOddCount

  • 循环中的索引包括数组的长度(&lt;=),因此在最后一次迭代中,它们尝试索引到数组中的最后一个元素。 Off-by-one error。这可以通过将条件更改为&lt; $array_length(而不是&lt;=)来解决,但请继续阅读

  • 没有理由使用 C 风格的循环,甚至没有对索引进行迭代。 (此处需要,因为使用了数组中的位置。)脚本语言提供了更简洁的方法

    foreach my $i1 (0 .. $#arraynumber) { 
        my $IntCount = 0;      
        foreach my $i2 (0 .. $#arraynumber) { 
            if ( $arraynumber[$i1] == $arraynumber[$i2] ) { 
                ...
    

    0..Nrange operator,它创建了该范围内的数字列表。语法$#array_name 是数组@array_name 中最后一个元素的索引。正是需要的。所以不需要数组长度

  • 用于检查代码的多个(六个)数组可以通过使用references 以更好、更简单的方式进行操作;查看复杂数据结构的教程perldsc,尤其是页面perllol,用于数组数组

简而言之:当您删除原型并修复一个错误时,您的代码似乎是正确的。


不仅仅是脚本——例如,C++11 引入了 range-based for loop

for (auto var: container) ...  // really const auto&, or auto&, or auto&&

链接(标准参考)说

用作更易读的等价于传统的for 循环[...]

【讨论】:

  • 我希望存储奇数的,但只存储奇数的。我用我的数组尝试了这个程序,甚至没有打印出来。
  • @ITM_Coder 此答案中发布的代码在复制粘贴中有两个拼写错误,根本无法运行(我检查的代码没有拼写错误)。已修复,并使用您的阵列检查了更正的版本。还在问题中的代码上添加了 cmets - 通过两个简单的修复是正确的
【解决方案2】:

使用哈希计算for 循环中出现的次数。然后使用grep 打印所需的元素,如下所示:

#!/usr/bin/env perl

use warnings;
use strict;
use feature qw( say );

my @array = (10,10,7,7,6,6,2,2,3,3,4,4,5,5,6,7,7,7,7,10,10);
my %cnt;

# Count each element of the array:
$cnt{$_}++ for @array;

# Print only the array elements that occurred an odd number of times,
# separated by ", ":
say join q{, }, grep { $cnt{$_} % 2 } @array;
# 6, 6, 6

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多