@all_matches = grep { ! ( $seensentence { $_->[0] .'-'. $_->[1] .'-'. $_->[5] } ++ ) } @all_matches;
目的:此代码从数组@all_matches(AoA)中删除某些元素的重复项.
我完全崩溃的尝试(?? ?? ??我不确定的地方):
Grep返回返回true的@all_matches元素.
哈希%seesentence的关键是??三个元素?? of @all_matches.由于散列只能有唯一键,因此第一次通过它的值会从undef(0)递增到1.下一次,它是一个定义的值,但是!表示grep仅在它是undef(与该元素关联的唯一值)时才返回它.
我的问题:
(1)我怎样才能转{$_-> [0] .’-‘. $_-> [1].’ – ‘. $_-> [5]}变成了HoH?
我被告知这是实现它的另一种(惯用的)方式.在黑暗中刺伤将是:
( {$_->[0] => 0,$_->[1] => 0,$_->[5] => 0} )++
(1b)因为我不明白原作是如何做我想要的.我读到-bareword等同于“-bareword”所以我尝试了:{“$_-> [0]”. “$_-> [1]”. “$_-> [5]”}它似乎完全相同.我仍然不明白:它是将每个元素分别视为一个键(a)(如一个键数组)还是它(b)正确:所有同时(因为.将它们连接成一个字符串)或者它( c)没有做我认为的事情?
(2)这是什么意思:$_-> [0] || $_-> [1] || $_-> [5]?它与上面没有相同的做法.
我读到:短路逻辑运算符返回最后一个值,所以它会检查{$_-> [0]}的值,如果有的话,我认为那里的值会增加,如果没有,它会检查下一个元素,直到没有为真,这是grep传递唯一值的时候.
谢谢你的时间,我尽量尽可能彻底(出错?)但是如果有任何遗漏,请告诉我.
解决方法
my @all_matches = ( ... ); { my %seen; my @no_dupes; foreach my $match ( @all_matches ) { my $first_item = $match->[0]; my $second_item = $match->[1]; my $third_item = $match->[5]; my $key = join '-',$first_item,$second_item,$third_item; if( not $seen{ $key }++ ) { push @no_dupes,$match; } } @all_matches = @no_dupes; }
换句话说,原始编码器使用$match中保存的数组引用创建一个哈希键,对于$match-> [0],1和5的每个引用索引.由于哈希键是唯一的,任何重复项将在推入@no_dupes之前检查密钥是否已存在将被删除.
grep {}机制只是一个更有效的代码(即,更快的类型,没有一次性变量)成语来完成同样的事情.如果它有效,为什么要重构呢?你需要改进的是什么不做?
要对HoH做同样的事情,你可以这样做:
my @all_matches = ( ... ); { my %seen; my @no_dupes; foreach my $match ( @all_matches ) { my $first_item = $match->[0]; my $second_item = $match->[1]; my $third_item = $match->[5]; if( not $seen{ $first_item }->{ $second_item }->{ $third_item }++ ) { push @no_dupes,$match; } } @all_matches = @no_dupes; }
哪个可以翻译成grep如下:
my @all_matches = ( ... ); { my %seen; @all_matches = grep { not $seen{$_->[0]}->{$_->[1]}{$_->[5]}++ } @all_matches; }
但是,在这种情况下,我没有看到构建数据结构的明显优势,除非您打算使用%稍后看到的其他内容.
关于||运算符,那是一种不同的动物.我想不出在这种情况下使用它的任何有用方法.例如,“$a || $b || $c”的逻辑短路运算符测试$a的布尔真值.如果是,则返回其值.如果它是假的,它会以同样的方式检查$b.如果它是假的,它会以同样的方式检查$c.但如果$a为真,则$b永远不会被检查.如果$b为真,则$c永远不会被检查.