Perl 两列平面文件到复杂的无序列表树
Perl two column flat file to a complex unordered list tree
我有一个从我们的 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 但我正在努力将初始示例转换为所需的格式。
我有一些代码将整个数据文件吸入一个数组,检查管理器值不为空,然后递归地尝试匹配树上的下一个管理器(直到它达到空值)这应该给我输出如:
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
以下程序接近您的要求:
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 可能会有所帮助,因为我相信您的问题是拓扑排序的一个实例。
我有一个从我们的 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 但我正在努力将初始示例转换为所需的格式。
我有一些代码将整个数据文件吸入一个数组,检查管理器值不为空,然后递归地尝试匹配树上的下一个管理器(直到它达到空值)这应该给我输出如:
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
以下程序接近您的要求:
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 可能会有所帮助,因为我相信您的问题是拓扑排序的一个实例。