我不知道“expand”是否是正确的词,但这是我想做的事情=)
此脚本
#!/usr/bin/perl
use warnings;
use strict;
my %HoA = (
group1 => [ "user1", "user2" ],
group2 => [ "group1", "user3" ],
group3 => [ "group1", "group2" ],
group4 => [ "group3", "user2" ],
);
foreach my $group ( keys %HoA ) {
print "$group: @{ $HoA{$group} }\n"
}
输出
group1: user1 user2
group2: group1 user3
group3: group1 group2
group4: group3 user4
我想要的是用成员替换数组中的组。即所以输出和$HoA
变为
group1: user1 user2
group2: user1 user2 user3
group3: user1 user2 user3
group4: user1 user2 user3 user4
也许“搜索和替换”并删除重复内容可以更好地解释我想要做什么?
答案 0 :(得分:3)
假设您提供的数据,以下循环将使用扩展数组创建新哈希。此算法假定组将按排序顺序解析(group2将仅依赖于group1,group3 on 1/2,...)。
my %expanded;
for my $group (sort keys %HoA) {
my %seen;
$expanded{$group} = [
grep {not $seen{$_}++}
map {exists $expanded{$_} ? @{$expanded{$_}} : $_}
@{$HoA{$group}}
];
print "$group: @{ $expanded{$group} }\n"
}
打印:
group1: user1 user2 group2: user1 user2 user3 group3: user1 user2 user3 group4: user1 user2 user3
如果您不能承担解决方案的命令,以下是有点蛮力,但应该有效:
my %HoA = (
group1 => [ "user1", "user2" ],
group2 => [ "group1", "user3" ],
group3 => [ "group1", "group2" ],
group4 => [ "user5", "group5" ],
group5 => [ "group3", "user2" ],
);
my @to_expand = keys %HoA;
my %final;
my $tries = @to_expand;
to_expand: while (@to_expand and $tries) {
my $next = shift @to_expand;
my (@users, @groups);
for (@{ $HoA{$next} }) {
if (/^group/) {
push @groups, $_;
} else {
push @users, $_;
}
}
for my $group (@groups) {
if (exists $final{$group}) {
push @users, @{$final{$group}}
} else {
$tries--;
push @to_expand, $next;
next to_expand;
}
}
$tries++;
my %seen;
$final{$next} = [grep {not $seen{$_}++} @users];
}
if (@to_expand) {
print "error with groups: @to_expand\n";
}
for (sort keys %final) {
print "$_: @{$final{$_}}\n";
}
打印:
group1: user1 user2 group2: user3 user1 user2 group3: user1 user2 user3 group4: user5 user2 user1 user3 group5: user2 user1 user3
如果有错误(比如group3取决于group5),那么你将得到这个输出:
error with groups: group4 group5 group3 group1: user1 user2 group2: user3 user1 user2
对此可能有更好的算法。
答案 1 :(得分:3)
如果有递归,这将抛出一个错误 - 虽然不是万无一失,而不是优雅,但
use strict;
my %HoA = (
group1 => [ "user1", "user2" ],
group2 => [ "group1", "user3" ],
group3 => [ "group1", "group2" ],
group4 => [ "group3", "user2" ],
);
my %ex=(); # expanded hash
foreach my $g ( keys %HoA ) { # first population
$ex{$g} = {};
AddArrayToHash($ex{$g},$HoA{$g});
}
my $goon = 1;
my $cont =0;
while($goon) { # iterate
$goon=0;
die "too many iterations RECURSIVE DEFINITION?" if($cont++ >10) ;
foreach my $g ( keys %ex ) {
foreach my $u ( keys %{$ex{$g}} ) {
if($ex{$u}) {
delete $ex{$g}->{$u};
AddArrayToHash($ex{$g},[ keys %{$ex{$u}}] );
$goon = 1;
}
}
}
}
foreach my $group ( sort keys %ex ) {
print "$group: " . join(" ",sort keys %{$ex{$group}}) ."\n";
}
sub AddArrayToHash {
my($refhash,$refarray)=@_;
foreach my $e (@$refarray) {
$refhash->{$e} = 1;
}
}
答案 2 :(得分:2)
我不知道为什么人们不得不写这么多代码:
sub expand_group {
my ( $ref, $arref, $deep ) = @_;
croak 'Deep Recursion!' if ++$deep > scalar( keys %$ref );
return map {
exists $ref->{$_} ? expand_group( $ref, $ref->{$_}, $deep ) : $_
} @$arref
;
}
sub expand_groups {
my ( $block, $group_ref ) = @_;
while ( my ( $key, $val ) = each %$group_ref ) {
$block->( $key, expand_group( $group_ref, $val, 1 ));
}
}
expand_groups( sub { say join( ' ', @_ ); }, \%HoA );
答案 3 :(得分:2)
我会尝试像
这样的东西#!/usr/bin/perl
use warnings;
use strict;
my %HoA = (
group1 => [ "user1", "user2" ],
group2 => [ "group1", "user3" ],
group3 => [ "group1", "group2" ],
group4 => [ "group3", "user2" ],
);
my %users;
foreach my $group ( sort keys %HoA ) {
%users = ();
print "$group: ";
print_key($group, $HoA{$group});
print join " ", sort keys %users;
print "\n";
}
sub print_key {
my $group = shift;
foreach my $item (@{$HoA{$group}}) {
if (exists $HoA{$item}) {
print_key($item);
}
else {
$users{$item}++;
}
}
}