代码之家  ›  专栏  ›  技术社区  ›  coding_hero

在perl中计算包含元素的数组数

  •  3
  • coding_hero  · 技术社区  · 14 年前

    我想我看这个太久了。我有一些数据是这样的:

    @a = (
        { name => 'ethan', depth => 0 },
        { name => 'victoria', depth => 1 },
        { name => 'stephen', depth => 2 },
        { name => 'christopher', depth => 3 },
        { name => 'isabella', depth => 2 },
        { name => 'ethan', depth => 3 },
        { name => 'emma', depth => 0 },
        { name => 'michael', depth => 1 },
        { name => 'olivia', depth => 2 },
        { name => 'alexander', depth => 3 },
        { name => 'stephen', depth => 1 },
        { name => 'sophia', depth => 0 },
        { name => 'michael', depth => 1 },
        { name => 'ava', depth => 1 },
        { name => 'joshua', depth => 2 }
    );
    

    我可以想出一些方法来做到这一点,但它们都涉及多个循环,似乎有点野蛮和不雅。希望其他人能想出更好的解决办法。

    5 回复  |  直到 14 年前
        1
  •  2
  •   hobbs    14 年前

    我不是100%确定你的问题规格-这是正确的输出吗?

      alexander 1
            ava 1
    christopher 1
           emma 1
          ethan 1
       isabella 1
         joshua 1
        michael 2
         olivia 1
         sophia 1
        stephen 2
       victoria 1
    

    my @names = (
      # your @a above
    );
    
    my (%seen, %count);
    
    for my $entry (@names) {
      if ($entry->{depth} == 0) {
        ++$count{$_} for keys %seen;
        %seen = ();
      }
      ++$seen{ $entry->{name} };
    }
    
    ++$count{$_} for keys %seen;
    print "$_\t$count{$_}\n" for sort keys %count;
    

    也就是说,只需记录只有在到达树的根时才进入全局计数的名称。

        2
  •  1
  •   Sinan Ünür    14 年前

    还有一种方法:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my @data = (
        { name => 'ethan', depth => 0 },
        { name => 'victoria', depth => 1 },
        { name => 'stephen', depth => 2 },
        { name => 'christopher', depth => 3 },
        { name => 'isabella', depth => 2 },
        { name => 'ethan', depth => 3 },
        { name => 'emma', depth => 0 },
        { name => 'michael', depth => 1 },
        { name => 'olivia', depth => 2 },
        { name => 'alexander', depth => 3 },
        { name => 'stephen', depth => 1 },
        { name => 'sophia', depth => 0 },
        { name => 'michael', depth => 1 },
        { name => 'ava', depth => 1 },
        { name => 'joshua', depth => 2 }
    );
    
    my @trees;
    
    for my $x ( @data ) {
        push @trees, {} unless $x->{depth};
        $trees[-1]->{ $x->{name} } = undef;
    }
    
    my @names = keys %{ { map { $_->{name} => undef } @data } };
    for my $name ( sort @names ) {
        printf "%s appears in %d tree(s)\n",
            $name, scalar grep { exists $_->{$name} } @trees;
    }
    
        3
  •  1
  •   cHao    14 年前
    %count = ();
    for (@a)
    {
        %found = () unless $_->{depth};
        my $name = $_->{name};
        unless ($found{$name}) 
        {
            ++$count{$name};
            $found{$name} = 1;
        }
    }
    return %count;
    

        4
  •  1
  •   Hynek -Pichi- Vychodil Paulo Suassuna    14 年前

    我认为这是最短最简单的解决办法

    my (%count, %seen);
    for my $e (@a) {
      %seen = () unless $e->{depth};
      $count{$e->{name}}++ unless $seen{$e->{name}}++;
    }
    
    print "$_ => $count{$_}\n" for sort keys %count;
    

    alexander => 1
    ava => 1
    christopher => 1
    emma => 1
    ethan => 1
    isabella => 1
    joshua => 1
    michael => 2
    olivia => 1
    sophia => 1
    stephen => 2
    victoria => 1
    
        5
  •  0
  •   Daenyth    14 年前

    解决这个问题的方法是使用一个递归函数,映射到数组上。边大小写的深度为0,在这种情况下返回。否则,请保留根名称,在哈希计数器中递增其值,然后递归到子树中,只要该名称与根名称不匹配,就在子树中递增该名称,然后再次递归,等等。