如何计算 Perl 中出现的奇数?
How to count the odd number of occurrences in 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 ";
这是我的结果。
The Odd value for the first array is 15
The Odd value for the first array is 21
The Odd value for the first array is 21
The Odd value for the first array is 19
The Odd value for the first array is 2
The Odd value for the first array is 1
如果你看不出来。它打印数组中所有元素的计数,而不是返回出现奇数次的元素。另外我得到这个错误。
Use of uninitialized value in numeric eq (==) at OddCount.pl line 17.
第 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
使用bitwise AND——如果$n
设置了最低位则为真,所以如果它是奇数
那++$freq{$_} for @ary;
是一个Statement Modifier,运行对@ary
的每个元素的声明,其中当前元素的别名是$_
变量
这会打印
o1 => 3
o2 => 1
这种奇数频率元素(如果有的话)的打印是按元素的字母顺序排序的,就这样。请更改为可能需要的任何特定订单,或让我知道。
评论问题中的代码,通过两个简单的修复是正确的。
它在sub FindOddCount($)
中以错误的方式使用了prototypes。我怀疑这不是必需的,所以让我们不要详述它 - 只需放下它并使其成为 sub FindOddCount
循环中的索引 包括 数组的长度 (<=
) 所以在最后一次迭代中他们试图索引数组过去它的最后一个元素。 Off-by-one error。这可以通过将条件更改为 < $array_length
(而不是 <=
)来解决,但继续阅读
没有理由使用 C 风格的循环,甚至没有理由遍历索引。 (此处需要,因为使用了数组中的位置。)脚本语言提供更简洁的方式†
foreach my $i1 (0 .. $#arraynumber) {
my $IntCount = 0;
foreach my $i2 (0 .. $#arraynumber) {
if ( $arraynumber[$i1] == $arraynumber[$i2] ) {
...
0..N
是 range operator,它创建了该范围内的数字列表。语法 $#array_name
是数组 @array_name
中最后一个元素的索引。正是需要什么。所以不需要数组 length
用于检查代码的多个(六个)数组,可以通过使用 references; see the tutorial for complex data structures perldsc, and in particular the page perllol 以更好更简单的方式进行操作,对于数组的数组
简而言之:当您删除原型并修复差一错误时,您的代码似乎是正确的。
† 不仅是脚本——例如,C++11
引入了 range-based for loop
for (auto var: container) ... // really const auto&, or auto&, or auto&&
和 link(标准参考)说
Used as a more readable equivalent to the traditional for
loop [...]
使用散列计算 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
我有一个 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 ";
这是我的结果。
The Odd value for the first array is 15 The Odd value for the first array is 21 The Odd value for the first array is 21 The Odd value for the first array is 19 The Odd value for the first array is 2 The Odd value for the first array is 1
如果你看不出来。它打印数组中所有元素的计数,而不是返回出现奇数次的元素。另外我得到这个错误。
Use of uninitialized value in numeric eq (==) at OddCount.pl line 17.
第 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
使用bitwise AND——如果$n
设置了最低位则为真,所以如果它是奇数那
++$freq{$_} for @ary;
是一个Statement Modifier,运行对@ary
的每个元素的声明,其中当前元素的别名是$_
变量
这会打印
o1 => 3 o2 => 1
这种奇数频率元素(如果有的话)的打印是按元素的字母顺序排序的,就这样。请更改为可能需要的任何特定订单,或让我知道。
评论问题中的代码,通过两个简单的修复是正确的。
它在
sub FindOddCount($)
中以错误的方式使用了prototypes。我怀疑这不是必需的,所以让我们不要详述它 - 只需放下它并使其成为sub FindOddCount
循环中的索引 包括 数组的长度 (
<=
) 所以在最后一次迭代中他们试图索引数组过去它的最后一个元素。 Off-by-one error。这可以通过将条件更改为< $array_length
(而不是<=
)来解决,但继续阅读没有理由使用 C 风格的循环,甚至没有理由遍历索引。 (此处需要,因为使用了数组中的位置。)脚本语言提供更简洁的方式†
foreach my $i1 (0 .. $#arraynumber) { my $IntCount = 0; foreach my $i2 (0 .. $#arraynumber) { if ( $arraynumber[$i1] == $arraynumber[$i2] ) { ...
0..N
是 range operator,它创建了该范围内的数字列表。语法$#array_name
是数组@array_name
中最后一个元素的索引。正是需要什么。所以不需要数组 length用于检查代码的多个(六个)数组,可以通过使用 references; see the tutorial for complex data structures perldsc, and in particular the page perllol 以更好更简单的方式进行操作,对于数组的数组
简而言之:当您删除原型并修复差一错误时,您的代码似乎是正确的。
† 不仅是脚本——例如,C++11
引入了 range-based for loop
for (auto var: container) ... // really const auto&, or auto&, or auto&&
和 link(标准参考)说
Used as a more readable equivalent to the traditional
for
loop [...]
使用散列计算 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