【问题标题】:Need to find a string in group, then to find all groups where single group (containing a string) belongs to需要在组中找到一个字符串,然后找到单个组(包含一个字符串)所属的所有组
【发布时间】:2019-04-09 02:07:02
【问题描述】:

我有 text.csv 文件,其中包含 IP 地址和具有 IP 地址的组。我可以很容易地找到 IP 10.1.1.1 属于哪个单组。问题是我需要找到组(找到IP)也属于的所有组。假设可能有很多组。

我已尝试以下代码来查找 IP 所属的组,但我不知道如何在循环中查找其他组。让我们看一个文件 text.csv:

Group name,Group members
------------------------
Group1    ,Group2
Group2    ,Group3
Group3    ,10.1.1.1
Group4    ,10.1.1.1 
Group5    ,Group2

到目前为止我的代码:

my $ip = "10.1.1.1";         

$csv = Text::CSV->new({ sep_char => ',' });
open(DATA, "< :encoding(iso-8859-7)", "text.csv") or die "Could not open $!\n";               

 while (<DATA>) {    
  if ($csv->parse($_)) {

   @column_all           = $csv->fields();
   $column_name          = $column_all[0];
   $column_group_member  = $column_all[1];


   if ($column_group_member =~ /$ip/) {
    $object = $column_name;
    print $column_name;     
   }


   if ($column_group_member =~ /$objectH/) {
    print $column_name;
   }


  }
 }

这将只打印 Group3,因为它的 IP 为 10.1.1.1

结果应该是: Group3(因为它包含 IP 10.1.1.1) Group2(因为它包含 Group3) Group1(因为它包含 Group2)

【问题讨论】:

    标签: perl


    【解决方案1】:

    我们想知道每个成员属于哪些组,因此我们将创建一个以成员为键的数组哈希 (HoA),其中包含该成员(直接)所属的所有组。

    push @{ $hash{$key} }, $value; 是构建 HoA 的常用方法。

    构建此 HoA 后,我们将确定 IP 地址所属的组,然后我们将确定每个组所属的组,依此类推。

    如果 IP 属于两个属于同一个组的两个组(直接或其他),我们需要过滤掉我们之前看到的组。

    my %seen; my @unique = grep !$seen{$_}++, @values; 是过滤重复项的常用方法。

    解决方案:

    use strict;                            # ALWAYS use this.
    use warnings;                          # ALWAYS use this.
    use feature qw( say );
    
    use Sort::Key::Natural qw( natsort );  # Optional. Can use sort or leave unsorted instead.
    use Text::CSV_XS       qw( );          # Faster than Text::CSV, but otherwise identical.
    
    my $ip  = "10.1.1.1";
    my $qfn = "text.csv";
    
    my $csv = Text::CSV_XS->new({
       auto_diag => 2,                     # Die on errors.
       binary    => 1,                     # Should always have this.
    });
    
    # "DATA" already exists, and you shouldn't be using global vars.
    open(my $fh, "<:encoding(iso-8859-7)", $qfn)
       or die("Can't open \"$qfn\": $!\n");
    
    my %belongs_to;
    while ( my $row = $csv->getline($fh) ) {    # Proper way to use $csv
       my ($member, $group) = @$row;
    
       # Add $group to the array referenced by $belongs_to{$member}.
       # The array is autovivified as if we had used « $belongs_to{$member} //= []; ».
       push @{ $belongs_to{$member} }, $group;
    }
    
    # Recursively determine to which groups $ip belongs.
    my %groups;
    my @groups;
    my @todo = $ip;
    while (@todo) {
       my $member = shift(@todo);
    
       # Add every group we haven't encountered yet to @groups and @todo.
       my @new_groups = grep !$groups{$_}++, @{ $belongs_to{$member} };
       push @groups, @new_groups;
       push @todo,   @new_groups;
    }
    
    @groups = natsort @groups;  # Make the results more presentable.
    
    say for @groups;
    

    (有优化最后一部分的方法,但收益微乎其微,这里最重要的是最清晰。)

    【讨论】:

      猜你喜欢
      • 2022-10-13
      • 1970-01-01
      • 2012-06-28
      • 2018-10-03
      • 1970-01-01
      • 2015-12-15
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      相关资源
      最近更新 更多