为什么数组输出工作两次?为什么输出中的单词之间有多个 space?
Why does array output work twice? Why is there more than one space between words in the output?
我有一个 anagram 函数,它接收对单词数组的引用作为输入。该函数必须 return 一个散列,其键是从一组变位词中找到的第一个单词,值必须是对数组的引用,其中的每个元素都是该组中的一个单词,顺序为最早是在字典里遇到的。应删除集合中的相同单词,所有单词应减少为相同的大小写。
示例输入:
abc
BAc
BOOk
cab
one
Noe
rory
eon
Yror
rrYo
Koob
BoKo
ooKB
book
abc
示例输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book,abc
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
我的脚本:
#!/usr/bin/perl
use strict;
use utf8;
no warnings;
use 5.10.0;
my @list = qw(abc BAc BOOk cab one Noe rory eon Yror rrYo Koob BoKo ooKB book abc);
sub anagram {
my $arrayref = shift;
my $index = 0;
my @array;
my @uniq;
my @match;
my %hash;
my %uniq = ();
for (my $i = 0; $i < $#$arrayref; $i++ ) {
push @array, lc(@$arrayref[$i]);
}
say join ",", @array;
@uniq = grep { !$uniq{$_}++ } @array;
say join ",", @uniq;
while (@uniq) {
my @chars = split(//, @uniq[0]);
my @indexes;
my $regex = "[";
for (my $i = 0; $i < scalar @chars; $i++) {
$regex = $regex . $chars[$i];
}
$regex = $regex . "]{" . scalar @chars . "}";
for (my $i = 0; $i < scalar @uniq; $i++) {
if ($uniq[$i] =~ m/$regex/) {
push @indexes, $i;
$match[$index][$i] = $uniq[$i];
}
}
$hash{$uniq[0]} = $match[$index];
my $last_index = $#indexes;
for (my $i = $last_index; $i >= 0; $i--) {
splice @uniq, $indexes[$i], 1;
}
@indexes = ();
$index++;
}
return \%hash;
}
anagram(\@list);
my $result = anagram(\@list);
say "$_: @{$result->{$_}}" for sort keys %$result;
我的输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
- 为什么数组的内容显示两次?
21 say join ",", @array;
23 say join ",", @uniq;
我的输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
预期输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book,abc
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
- 为什么我输出的单词之间有多个 space?
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
- 为什么在删除重复项之前最后一个词
abc
丢失了?
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
- Why are the contents of the arrays displayed twice?
anagram(\@list);
my $result = anagram(\@list);
- Why is there more than one space between words in my output?
由于数组中的元素为空。
- Why are the contents of the arrays displayed twice?
那是因为它们是在您的 anagram()
子例程中使用 say()
打印的,并且您调用了该子例程两次。
- Why is there more than one space between words in my output?
如果您使用 Data::Dumper 来显示 $result
从 anagram()
返回时的内容,您会看到它看起来像这样:
$VAR1 = {
'book' => [
'book',
undef,
undef,
undef,
undef,
undef,
undef,
'koob',
'boko',
'ookb'
],
'rory' => [
'rory',
'yror',
'rryo'
],
'one' => [
'one',
'noe',
undef,
'eon'
],
'abc' => [
'abc',
'bac',
undef,
'cab'
]
};
看起来 undef
值与输出中的额外空格相对应。
也许你应该替换:
say "$_: @{$result->{$_}}" for sort keys %$result;
与:
say "$_: ", join ' ', grep { defined } @{$result->{$_}}
for sort keys %$result;
- Why is the last word abc lost before deleting duplicates?
您的代码中有四个 for
循环。您使用三种不同的方法来编写这些循环。
for (my $i = 0; $i < $#$arrayref; $i++ )
for (my $i = 0; $i < scalar @chars; $i++)
for (my $i = 0; $i < scalar @uniq; $i++)
my $last_index = $#indexes;
for (my $i = $last_index; $i >= 0; $i--)
最后三个循环按照您的预期工作(但对于您要执行的操作而言,它们都过于复杂)。但是,第一个问题导致了您的问题。
您似乎意识到 $#arrayname
给出数组中的最后一个索引(您在第一个和最后一个循环中使用它)。但是你的第一个循环似乎有一个“off-by-one”错误。当 $i
不再小于 $#$arrayref
时,您将停止迭代循环。这省略了数组的最后一个元素——我不认为你打算这样做。如果您将第一个循环替换为:
for (my $i = 0; $i <= $#$arrayref; $i++ ) # Note: >= instead of >
然后你得到你期望的结果。
我预计您会犯此错误,因为在其他循环中您使用 @arrayname
而不是 $#arrayname
。但是 @arrayname
为您提供数组中元素的 number,而不是最后一个索引。对于任何数组,@arrayname
总是比 $#arrayname
.
多 1
您很少会发现像您这样使用“C 风格”for
循环的 Perl 程序员。那是因为他们很容易犯这种错误。但是,方便的是,我们有通常更容易理解的 foreach
样式循环。在这种形式中,我们只是生成一个值列表并遍历该列表。如果你正在遍历一个数组并需要它的索引值,我总是建议 $#arrayname
而不是 @arrayname
。
你的四个循环可以重写为:
foreach my $i (0 .. $#$arrayref)
foreach my $i (0 .. $#chars)
foreach my $i (0 .. $#uniq)
# This is slightly harder as we need the
# indexes in reverse order. So use "reverse()".
foreach my $i (reverse 0 .. $indexes)
在某些情况下,您仅使用 $i
来访问数组的元素。在这些情况下,只遍历列表本身比遍历索引更简单。例如,您的第一个循环是:
for (my $i = 0; $i < $#$arrayref; $i++ ) {
push @array, lc(@$arrayref[$i]);
}
最好写成:
for my $el (@$arrayref) {
push @array, lc $el;
}
甚至(因为 @array
开始是空的):
my @array = map { lc } @$arrayref;
但我承认这涉及到一些稍微深奥的 Perl 功能:-)
更新: 我注意到您的代码中有 no warnings
。在编写 Perl 代码时,您应该始终打开警告。 use warnings
您的代码省略了两个警告(其中一个警告重复了几次)。
Scalar value @uniq[0] better written as $uniq[0] at anagram2 line 25.
您有:
my @chars = split(//, @uniq[0]);
数组的单个元素是标量值,因此应该使用 $
而不是 @
来访问。这一行应该是:
my @chars = split(//, $uniq[0]);
Use of uninitialized value in join or string at anagram2 line 51.
这是我们在上面讨论并修复的 $result
中未定义值的问题。
最好始终保持 use warnings
开启并解决它向您显示的任何问题。
请调查以下代码片段是否符合您的问题。
use strict;
use warnings;
my($words,$seen);
while( <DATA> ) {
chomp;
s/^\s+|\s+\z//;
my $val = lc $_;
my $key = join('', sort split('', $val));
push @{$words->{$key}}, $val unless $seen->{$val}++;
}
printf "%-5s : %s\n", $words->{$_}[0], join(', ', @{$words->{$_}})
for sort keys %{$words};
exit 0;
__DATA__
abc
BAc
BOOk
cab
one
Noe
rory
eon
Yror
rrYo
Koob
BoKo
ooKB
book
abc
输出
abc : abc, bac, cab
book : book, koob, boko, ookb
one : one, noe, eon
rory : rory, yror, rryo
我有一个 anagram 函数,它接收对单词数组的引用作为输入。该函数必须 return 一个散列,其键是从一组变位词中找到的第一个单词,值必须是对数组的引用,其中的每个元素都是该组中的一个单词,顺序为最早是在字典里遇到的。应删除集合中的相同单词,所有单词应减少为相同的大小写。
示例输入:
abc
BAc
BOOk
cab
one
Noe
rory
eon
Yror
rrYo
Koob
BoKo
ooKB
book
abc
示例输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book,abc
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
我的脚本:
#!/usr/bin/perl
use strict;
use utf8;
no warnings;
use 5.10.0;
my @list = qw(abc BAc BOOk cab one Noe rory eon Yror rrYo Koob BoKo ooKB book abc);
sub anagram {
my $arrayref = shift;
my $index = 0;
my @array;
my @uniq;
my @match;
my %hash;
my %uniq = ();
for (my $i = 0; $i < $#$arrayref; $i++ ) {
push @array, lc(@$arrayref[$i]);
}
say join ",", @array;
@uniq = grep { !$uniq{$_}++ } @array;
say join ",", @uniq;
while (@uniq) {
my @chars = split(//, @uniq[0]);
my @indexes;
my $regex = "[";
for (my $i = 0; $i < scalar @chars; $i++) {
$regex = $regex . $chars[$i];
}
$regex = $regex . "]{" . scalar @chars . "}";
for (my $i = 0; $i < scalar @uniq; $i++) {
if ($uniq[$i] =~ m/$regex/) {
push @indexes, $i;
$match[$index][$i] = $uniq[$i];
}
}
$hash{$uniq[0]} = $match[$index];
my $last_index = $#indexes;
for (my $i = $last_index; $i >= 0; $i--) {
splice @uniq, $indexes[$i], 1;
}
@indexes = ();
$index++;
}
return \%hash;
}
anagram(\@list);
my $result = anagram(\@list);
say "$_: @{$result->{$_}}" for sort keys %$result;
我的输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
- 为什么数组的内容显示两次?
21 say join ",", @array;
23 say join ",", @uniq;
我的输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
预期输出:
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book,abc
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
- 为什么我输出的单词之间有多个 space?
abc: abc bac cab
book: book koob boko ookb
one: one noe eon
rory: rory yror rryo
- 为什么在删除重复项之前最后一个词
abc
丢失了?
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb,book
abc,bac,book,cab,one,noe,rory,eon,yror,rryo,koob,boko,ookb
- Why are the contents of the arrays displayed twice?
anagram(\@list);
my $result = anagram(\@list);
- Why is there more than one space between words in my output?
由于数组中的元素为空。
- Why are the contents of the arrays displayed twice?
那是因为它们是在您的 anagram()
子例程中使用 say()
打印的,并且您调用了该子例程两次。
- Why is there more than one space between words in my output?
如果您使用 Data::Dumper 来显示 $result
从 anagram()
返回时的内容,您会看到它看起来像这样:
$VAR1 = {
'book' => [
'book',
undef,
undef,
undef,
undef,
undef,
undef,
'koob',
'boko',
'ookb'
],
'rory' => [
'rory',
'yror',
'rryo'
],
'one' => [
'one',
'noe',
undef,
'eon'
],
'abc' => [
'abc',
'bac',
undef,
'cab'
]
};
看起来 undef
值与输出中的额外空格相对应。
也许你应该替换:
say "$_: @{$result->{$_}}" for sort keys %$result;
与:
say "$_: ", join ' ', grep { defined } @{$result->{$_}}
for sort keys %$result;
- Why is the last word abc lost before deleting duplicates?
您的代码中有四个 for
循环。您使用三种不同的方法来编写这些循环。
for (my $i = 0; $i < $#$arrayref; $i++ )
for (my $i = 0; $i < scalar @chars; $i++)
for (my $i = 0; $i < scalar @uniq; $i++)
my $last_index = $#indexes;
for (my $i = $last_index; $i >= 0; $i--)
最后三个循环按照您的预期工作(但对于您要执行的操作而言,它们都过于复杂)。但是,第一个问题导致了您的问题。
您似乎意识到 $#arrayname
给出数组中的最后一个索引(您在第一个和最后一个循环中使用它)。但是你的第一个循环似乎有一个“off-by-one”错误。当 $i
不再小于 $#$arrayref
时,您将停止迭代循环。这省略了数组的最后一个元素——我不认为你打算这样做。如果您将第一个循环替换为:
for (my $i = 0; $i <= $#$arrayref; $i++ ) # Note: >= instead of >
然后你得到你期望的结果。
我预计您会犯此错误,因为在其他循环中您使用 @arrayname
而不是 $#arrayname
。但是 @arrayname
为您提供数组中元素的 number,而不是最后一个索引。对于任何数组,@arrayname
总是比 $#arrayname
.
您很少会发现像您这样使用“C 风格”for
循环的 Perl 程序员。那是因为他们很容易犯这种错误。但是,方便的是,我们有通常更容易理解的 foreach
样式循环。在这种形式中,我们只是生成一个值列表并遍历该列表。如果你正在遍历一个数组并需要它的索引值,我总是建议 $#arrayname
而不是 @arrayname
。
你的四个循环可以重写为:
foreach my $i (0 .. $#$arrayref)
foreach my $i (0 .. $#chars)
foreach my $i (0 .. $#uniq)
# This is slightly harder as we need the
# indexes in reverse order. So use "reverse()".
foreach my $i (reverse 0 .. $indexes)
在某些情况下,您仅使用 $i
来访问数组的元素。在这些情况下,只遍历列表本身比遍历索引更简单。例如,您的第一个循环是:
for (my $i = 0; $i < $#$arrayref; $i++ ) {
push @array, lc(@$arrayref[$i]);
}
最好写成:
for my $el (@$arrayref) {
push @array, lc $el;
}
甚至(因为 @array
开始是空的):
my @array = map { lc } @$arrayref;
但我承认这涉及到一些稍微深奥的 Perl 功能:-)
更新: 我注意到您的代码中有 no warnings
。在编写 Perl 代码时,您应该始终打开警告。 use warnings
您的代码省略了两个警告(其中一个警告重复了几次)。
Scalar value @uniq[0] better written as $uniq[0] at anagram2 line 25.
您有:
my @chars = split(//, @uniq[0]);
数组的单个元素是标量值,因此应该使用 $
而不是 @
来访问。这一行应该是:
my @chars = split(//, $uniq[0]);
Use of uninitialized value in join or string at anagram2 line 51.
这是我们在上面讨论并修复的 $result
中未定义值的问题。
最好始终保持 use warnings
开启并解决它向您显示的任何问题。
请调查以下代码片段是否符合您的问题。
use strict;
use warnings;
my($words,$seen);
while( <DATA> ) {
chomp;
s/^\s+|\s+\z//;
my $val = lc $_;
my $key = join('', sort split('', $val));
push @{$words->{$key}}, $val unless $seen->{$val}++;
}
printf "%-5s : %s\n", $words->{$_}[0], join(', ', @{$words->{$_}})
for sort keys %{$words};
exit 0;
__DATA__
abc
BAc
BOOk
cab
one
Noe
rory
eon
Yror
rrYo
Koob
BoKo
ooKB
book
abc
输出
abc : abc, bac, cab
book : book, koob, boko, ookb
one : one, noe, eon
rory : rory, yror, rryo