perl - 如何计算 Perl 中出现的奇数次?
问题描述
我在 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 行是比较第一个数组和第二个数组的位置。然而,这些值被清楚地实例化了,当我打印出来时它们就起作用了。问题是什么?
解决方案
为数组构建频率哈希,然后通过它查看哪些元素具有奇数
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 & 1
使用按位与- 如果$n
设置了最低位,则为真,所以如果它是奇数那
++$freq{$_} for @ary;
是一个Statement Modifier@ary
,为当前元素被$_
变量别名的每个元素运行语句
这打印
o1 => 3 o2 => 1
这种奇频元素(如果有)的打印按元素的字母顺序排序,就是这样。请更改为可能需要的任何特定顺序,或让我知道。
对问题中的代码的评论,通过两个简单的修复是正确的。
它以错误的方式使用原型来达到目的,在
sub FindOddCount($)
. 我怀疑这不是必需的,所以我们不要纠缠于它 - 只需放弃它并实现它sub FindOddCount
循环中的索引包括
<=
数组的长度(差一个错误。这可以通过将条件更改为< $array_length
(而不是<=
)来解决,但请继续阅读没有理由使用 C 风格的循环,甚至没有对索引进行迭代。(此处需要,因为使用了数组中的位置。)脚本语言提供了更简洁的方法†</sup>
foreach my $i1 (0 .. $#arraynumber) { my $IntCount = 0; foreach my $i2 (0 .. $#arraynumber) { if ( $arraynumber[$i1] == $arraynumber[$i2] ) { ...
那
0..N
是范围运算符,它创建该范围内的数字列表。语法$#array_name
是数组中最后一个元素的索引@array_name
。正是需要的。所以不需要数组长度用于检查代码的多个(六个)数组可以通过使用引用以更好、更简单的方式进行操作;请参阅有关复杂数据结构perldsc的教程,尤其是perllol页面,用于数组数组
简而言之:当您删除原型并修复一个错误时,您的代码似乎是正确的。
†</sup> 不仅是脚本——例如,C++11
引入了基于范围的 for 循环
for (auto var: container) ... // really const auto&, or auto&, or auto&&
并且链接(标准参考)说
用作更易读的等价于传统
for
循环 [...]
推荐阅读
- python - Locust 在暂时收到错误 500 后停止
- angularjs - 如何从凉亭组件转移到节点模块
- python - 在模型编译之前/之后使用“conv_base.trainable = False”的模型差异
- bison - 在函数“yyparse”中:y.tab.c:未定义对“ex”的引用
- java - 必要时折叠对象列表的最佳解决方案
- java - 在多个 jar 中外部化类
- python - 使用 mplcursors.cursor().connect() 显示栏名称
- javascript - 为什么我的 HTML 按钮在尝试切换到网页的不同部分时不起作用?
- javascript - 你如何获得 showDirectoryPicker(); 从文件系统访问 Api 到即使您将 dirHandle 存储在 IndexDB 中也不会请求许可
- javascript - 如何在标题中插入特殊脚本?