理解代码:Hash,grep for duplicatelicates(修改为检查多个元素)

Jon*_*Jon 6 perl

码:

@all_matches = grep
{
    ! ( $seensentence
    {
        $_->[0] .'-'. $_->[1] .'-'. $_->[5]
    }
    ++ )
}
@all_matches;
Run Code Online (Sandbox Code Playgroud)

目的:此代码从阵列中删除某些元素的重复项,@all_matches即AoA.

我完全崩溃的尝试(?? ?? ??我不确定的地方):

Grep返回@all_matches返回true 的元素.

哈希的关键%seensentence是三个元素?? 的@all_matches.由于散列只能有唯一键,所以第一次通过它的值从undef(0)递增到1.下一次,它是一个定义的值,但是!只有当它的undef(相关的唯一值)时,grep才会返回它用那个元素).


我的问题:

(1)如何{$_->[0] .'-'. $_->[1] .'-'. $_->[5]}++变成HoH?

我被告知这是实现它的另一种(惯用的)方式.在黑暗中刺伤将是:

( {$_->[0] => 0,
$_->[1] => 0,
$_->[5] => 0} )++
Run Code Online (Sandbox Code Playgroud)

(1b)因为我不明白原作是如何做我想要的.我读到的-bareword是相同的,"-bareword"所以我尝试过:{"$_->[0]" . "$_->[1]". "$_->[5]"}它看起来完全相同.我仍然不明白:它是将每个元素分别视为一个键(a)(如一个键数组)还是它(b)正确:所有同时(因为.将它们连接成一个字符串)或者是它(c) )不做我认为的事情?

(2)这是什么意思:$_->[0] || $_->[1] || $_->[5]?它与上面没有相同的做法.

我读到:短路逻辑运算符返回最后一个值,所以它会检查一个值,{$_->[0]}如果有一个,我认为那里的值会增加,如果没有它会检查下一个元素,直到没有为真,这是当grep传递唯一值时.


谢谢你的时间,我尽量尽可能彻底(出错?)但是如果有任何遗漏,请告诉我.

Dav*_*idO 5

首先让我们把它grep变成一个foreach循环,这样我们就可以更清楚地检查它.为了清楚起见,我将把一些习语扩展为更大的构造.

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;
}
Run Code Online (Sandbox Code Playgroud)

换句话说,原来的编码器创建使用$比赛举行的数组引用的哈希键,为每个所指指数$match->[0],15.由于散列键是唯一的,因此在推入之前检查密钥是否已存在,将删除任何重复项@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;
}
Run Code Online (Sandbox Code Playgroud)

哪个可以翻译成grep如下:

my @all_matches = ( ... );
{
    my %seen;
    @all_matches = grep { not $seen{$_->[0]}->{$_->[1]}{$_->[5]}++ } @all_matches;
}
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,我没有看到构建数据结构的明显优势,除非您打算%seen稍后使用其他内容.

对于||操作员来说,这是一种不同的动物.我想不出在这种情况下使用它的任何有用方法.例如," $a || $b || $c" 的逻辑短路运算符测试布尔的真实性$a.如果是,则返回其值.如果它是假的,它会$b以同样的方式检查.如果它是假的,它会$c以同样的方式检查.但如果$a是真的,$b永远不会被检查.如果$b是真的,$c永远不会被检查.