首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Perl,使用两个不同的哈希表生成新数据(新哈希)。

Perl,使用两个不同的哈希表生成新数据(新哈希)。
EN

Stack Overflow用户
提问于 2012-04-23 07:17:07
回答 2查看 588关注 0票数 3

我遇到了一个非常复杂的问题(以我作为新手的角度),我不知道如何解决这个问题。我能想到工作流,而不是脚本。

我的文件A如下所示:教师(制表符)Student1(空格)Student2(空格)。

代码语言:javascript
运行
复制
Fiona       Nicole Sherry 
James       Alan Nicole
Michelle    Crystal 
Racheal     Bobby Dan Nicole

有时,当有两个相同的名称(例如,John1,John2)时,它们的名字旁边就有数字。如果学生有两个以上的顾问,他们也可能重叠。

文件B是一个由教师组成的文件。它看起来很相似,但这些值是逗号分隔的。

代码语言:javascript
运行
复制
Fiona       Racheal,Jack
Michelle    Racheal
Racheal     Fiona,Michelle
Jack        Fiona

文件B中的趋势是,一个键有多个值,每个值也成为一个键,可以很容易地找到与谁分组的人。

我想要的结果是,哪些学生可能会根据他们的老师/群体接受类似的教育,所以我希望这个脚本能够做到以下几点:

  1. 将文件A存储到散列中并关闭
  2. 打开档案B,查看每一位老师是否有学生(有些可能没有,实际的名单相当大)。所以,如果我选第一位老师菲奥娜,它会查看存储的文件A哈希表,看看是否有菲奥娜。如果有,(在本例中是Nicole和Sherry),将它们分别弹出作为新哈希表的新键。 $data=$_;$data=~/^(\S+)\s+(.*)$/;$TeacherA=$1;$group=$2;
  3. 然后,看看和菲奥娜在一起的一群老师(瑞秋,杰克)。一次带一人(雷查尔) 若(定义?){时间($list=~/(\w+)(.*)/) { $TeacherB=$1;$group=$2;
  4. 看看A档案给瑞秋的学生们。
  5. 将它们作为从步骤2生成的学生键的值(逗号分隔)填充。
  6. 打印学生-学生和教师小组。 妮可·鲍比,丹,妮可·菲奥娜·雷查尔·雪莉·鲍比,丹,妮可·菲奥娜·拉查尔 由于菲奥娜小组的下一位老师杰克没有任何学生,所以他不会出现在这个成绩中。例如,如果他有大卫,结果将是: 妮可·鲍比,丹,妮可·菲奥娜·雷查尔·雪莉·鲍比,丹,妮可·菲奥娜·妮可·妮可·菲奥娜·杰克

我很抱歉问了这么复杂而具体的问题。我希望其他正在做这种事情的人能从答案中获益。非常感谢您的帮助和答复。你是我唯一的帮助来源。

EN

回答 2

Stack Overflow用户

发布于 2012-04-23 09:26:30

这是一个相当奇怪的方式来看待数据,但我想我让它的工作方式,你试过。这将是有趣的,看看为什么你希望数据是那样的。下一次也许提供列标题。了解你为什么以某种方式做某事,常常会使你更容易想到实现它的方法,海事组织。

所以我就是这么做的。不要感到困惑,我把你的值从文件A和文件B放到标量中,并更改了读取它们的部分。

代码语言:javascript
运行
复制
my $file_a = qq~Fiona\tNicole Sherry
James\tAlan Nicole
Michelle\tCrystal
Racheal\tBobby Dan Nicole
~;

my $file_b = qq~Fiona\tRacheal,Jack
Michelle\tRacheal
Racheal\tFiona,Michelle
Jack\tFiona
~;

之后,继续阅读“文件”。

代码语言:javascript
运行
复制
# 1: Store file A in a hash
my (%file_a);
foreach my $a (split /\n/, $file_a) {
  my @temp = split /\t/, $a;
  $file_a{$temp[0]} = $temp[1];
}

# 2: Go through file B
foreach my $b (split /\n/, $file_b) {
  my @line_b = split /\t/, $b;
  # Look in stored file A if the teacher is there
  if (exists $file_a{$line_b[0]}) {
    my (%new_hash_table, @teachers);
    # Put all the students of this teacher into a new hash
    $new_hash_table{$_} = '' foreach split / /, $file_a{$line_b[0]};

    # 3: Take one of the group of teachers who are grouped with the 
    # current teacher at a time
    foreach my $teacher (split /,/, $line_b[1]) {
      if (exists $file_a{$teacher}) {
        # 4: This teacher from the group has students listen in file A
        push @teachers, $teacher; # Store the teacher's name for print later
        foreach (keys %new_hash_table) {
          # 5: Fill the students as csv for the student keys from step 2
          $new_hash_table{$_} = join(',', split(/ /, $file_a{$teacher}));
        }
      }
    }
    foreach my $student (keys %new_hash_table) {
      # 6: Print...        
      print join("\t", 
        # Student-student relation
        $student, $new_hash_table{$student}, 
        # Teacher-teacher relation
        $line_b[0], @teachers);
      print "\n";
    }
  }
}

对于我来说,它提供了以下输出:

代码语言:javascript
运行
复制
Sherry  Bobby,Dan,Nicole    Fiona   Racheal
Nicole  Bobby,Dan,Nicole    Fiona   Racheal
Crystal Bobby,Dan,Nicole    Michelle    Racheal
Bobby   Crystal Racheal Fiona   Michelle
Nicole  Crystal Racheal Fiona   Michelle
Dan Crystal Racheal Fiona   Michelle

这可能很奇怪,因为我没有所有的价值观。

无论如何,有几件事要说。

在示例代码中,您使用像$data=~/^(\S+)\s+(.*)$/;这样的正则表达式来获取一个简单的两列列表的值。使用分裂算子来实现这一点要容易得多。

当您使用<FILEHANDLE>语法从文件中读取时,可以将希望您的行进入while循环的标量放入如下所示:

代码语言:javascript
运行
复制
while (my $data = <GROUP>) {
      chomp $data

此外,常见还可以用大写格式编写文件句柄名。

我建议您看看‘学习Perl’。其中的散列和数组的基本概念应该足以完成像这样的任务。希望这能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2012-04-23 09:29:49

我想不出你为什么想要这些多余的数据,而你只需要查看A文件就能很好地知道谁在接受类似的教育.但是,这里有一种在perl中这样做的方法。

代码语言:javascript
运行
复制
$data = {};
# pull in students
open(IN, "students.txt");
while(my $line = <IN>) {
  chomp($line);
  my ($teacher, @students) = split(/\s+/,$line);
  $data->{$teacher}->{students} = \@students;
}
close IN;
# pull in teachers
open(IN, "teachers.txt");
while(my $line = <IN>) {
  chomp($line);
  my ($teacher, $supporters) = split(/\s+/,$line);
  my @supporters = split(/,/,$supporters);
  $data->{$teacher}->{supporters} = \@supporters;
}
close IN;
# make the output
foreach my $teacher (keys %{$data}){
  foreach my $teacher_student (@{$data->{$teacher}->{students}}) {
    foreach my $supporter (@{$data->{$teacher}->{supporters}}){
      my $num_supporter_students = @{$data->{$supporter}->{students}} + 0;
      if($num_supporter_students) {

        print "$teacher_student\t" . 
              join(",",@{$data->{$supporter}->{students}}) .
              "\t$teacher\t$supporter\n";
      }
    }
  }
}

当对问题中列出的数据运行时,它返回:

代码语言:javascript
运行
复制
Crystal Bobby,Dan,Nicole    Michelle    Racheal
Nicole  Bobby,Dan,Nicole    Fiona   Racheal
Sherry  Bobby,Dan,Nicole    Fiona   Racheal
Bobby   Nicole,Sherry   Racheal Fiona
Bobby   Crystal Racheal Michelle
Dan Nicole,Sherry   Racheal Fiona
Dan Crystal Racheal Michelle
Nicole  Nicole,Sherry   Racheal Fiona
Nicole  Crystal Racheal Michelle
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10276320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档