Perl两列平面文件到一个复杂的无序列表树

时间:2015-06-29 05:29:59

标签: algorithm perl parsing tree perl-data-structures

我有一个组织结构图的数据文件,它已经从我们的AD结构中拉出来,看起来像这样,管理器是第一个字段,员工是第二个 - 在某些情况下,经理会照顾一些员工:

__EXAMPLE__
user4   user8
user8   user9
    user1
user1   user2
user2   user3
user2   user5
user2   user4
user3   user5
user4   user6
user4   user7

这需要在HTML无序列表中输出,例如:

# Intended output
#
# <ul>
#   <li>user1</li>
#   <ul>
#       <li>user2</li>
#       <ul>
#           <li>user3</li>
#           <ul>
#               <li>user5</li>
#           </ul>
#           <li>user4</li>
#           <ul>
#               <li>user6</li>
#               <li>user7</li>
#               <li>user8</li>
#             <ul>
#               <li>user9</li>
#             </ul>
#           </ul>
#       </ul>   
#   </ul>
# </ul>

我认为我可以在这个位置使用示例代码:Parse Text file and create complex tree structure in perl但是我很难将初始示例变成所需的格式。

我有一些代码将整个数据文件吸入数组,检查Manager值是否为null,然后递归尝试匹配树上的下一个管理器(直到它达到null),这应该给我输出像:

user1
user1 user2
user1 user2 user3
user1 user2 user3 user5
user1 user2 user4
user1 user2 user4 user6
user1 user2 user4 user7
user1 user2 user4 user8
user1 user2 user4 user8 user9

不幸的是,我的Perl非常生疏,我的代码看起来很糟糕;我不确定我是以最好的方式接近这个,所以我希望得到一些比我更聪明的人的智慧。

当前示例:

#!/usr/bin/perl
#
use strict;
use warnings;

my @Complete = <DATA>;

foreach my $line (@Complete) {
    chomp($line);
    my ($fl, $usr) = split(/\t/, $line); #Formal Leader && User
    foreach my $leader (@Complete) {
        chomp($leader);
        if ($leader =~ /$fl$/) {
            $line = $leader."\t".$usr;
            ($fl,$usr) = split(/\t/, $line, 2);
            $leader = '';
        }
        last if ($fl eq '');
    }
    print "'".$line."'\n";
}

__DATA__
user4   user8
user8   user9
    user1
user1   user2
user2   user3
user2   user5
user2   user4
user3   user5
user4   user6
user4   user7

1 个答案:

答案 0 :(得分:1)

以下程序接近你想要的程序:

use strict;
use warnings;

use HTML::Entities;

sub render {
    my ($underlings_of, $level, $key) = @_;
    my $underlings = $underlings_of->{$key} or return;
    print "  " x $level, "<ul>\n";
    for my $underling (sort @$underlings) {
        print "  " x ($level + 1), "<li>", encode_entities($underling), "</li>\n";
        render($underlings_of, $level + 1, $underling);
    }
    print "  " x $level, "</ul>\n";
}

my %underlings_of;

while (my $line = readline DATA) {
    chomp $line;
    my ($mgr, $emp) = split /\t/, $line;
    push @{$underlings_of{$mgr}}, $emp;
}

render(\%underlings_of, 0, '');

__DATA__
user4   user8
user8   user9
    user1
user1   user2
user2   user3
user2   user5
user2   user4
user3   user5
user4   user6
user4   user7

它产生以下输出:

<ul>
  <li>user1</li>
  <ul>
    <li>user2</li>
    <ul>
      <li>user3</li>
      <ul>
        <li>user5</li>
      </ul>
      <li>user4</li>
      <ul>
        <li>user6</li>
        <li>user7</li>
        <li>user8</li>
        <ul>
          <li>user9</li>
        </ul>
      </ul>
      <li>user5</li>
    </ul>
  </ul>
</ul>

用户user5列出两次,因为它们在输入层次结构中显示两次,位于user2下方和user3下方。这意味着你的结构不是一棵树,它是一个有向无环(希望)的图。

对于其他方法,https://en.wikipedia.org/wiki/Topological_sorting可能会有所帮助,因为我认为您的问题是拓扑排序的一个实例。