CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
recursive subroutine for constructing hash

 



zohman
Novice

Apr 23, 2016, 6:55 AM

Post #1 of 10 (2603 views)
recursive subroutine for constructing hash Can't Post

Hi,

i need to reorganize a hash from input i have,

The data structure contain machines\users and groups
machines and users always exist as values of a group, groups can be key or values of another group.
values of machines\users always start with (,
values will never contain groups and users/machines at the same value.
structure will never contain anything else.
Inside the $info example I cover all of the options that can be in a real structure.


Code
my $info =  { 	'su_u_av_fc_rel'     => '(-,ebenzin1,) (-,nmigdal,)', 
'skl_rtl_users__n72' => 'skl_rtl_users__n14 skl_rtl_users__n15 skl_rtl_users__n56 sys_triple_group',
'skl_rtl_users__n15' => '(-,dbenita,) (-,dbenner,) (-,dbenyose,) (-,dbgurura,)',
'skl_rtl_users__n14' => '(-,csmithhi,) (-,csnguyen,) (-,csnider,) (-,csoni,)',
'skl_rtl_users__n56' => '(-,sgluxman,) (-,sgoh9,) (-,sgoldenb,) (-,sgollapu,)',
'sys_rh_alldisks' => 'sys_rh_backup sys_rh_rsync sys_rh_start sys_triple_group',
'sys_rh_backup' => '(iillsbk0100,-,) (iillsbk0101,-,)',
'sys_rh_rsync' => 'sys_rh_rsync__n1 sys_rh_rsync__n2 sys_triple_group sys_rh_nis3',
'sys_rh_nis3' => 'sys_rh_nis33 sys_rh_nis32',
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_rsync__n1' => '(icsl0944,-,) (icsl0945,-,) (icsl2878,-,)',
'sys_rh_rsync__n2' => '(irsync107,-,) (irsync108,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)',
'coe73_users__n53' => '(-,wwang69,) (-,wwong23,) (-,wwong5,) (-,wwong8,) (-,wwsee,) (-,wyeohx,) (-,wyuan,) (-,xdang,) (-,xiaomin2,)',
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'iclbuild' => '(biur7,-,) (biur9,-,) (biur10,-,) (biur11,-,) (biur12,-,) (biur13,-,)',
'sys_rh_start' => '(iinf069,-,) (iinf157,-,)'
};


i created some subroutine that make all the job for me
but it's not recursive.. and gos only 5 groups deep,
and the code starting to be a mass..

this is the sub:


Code
sub parse { 

my ($info) = @_;
my $map_data = {};

foreach my $key (keys %{$info}){
if ($info->{$key} !~ /^\(/) {
my @list = split(' ', $info->{$key});
foreach my $key2 (@list) {
if ($info->{$key2} !~ /^\(/) {
my @list2 = split(' ', $info->{$key2});
foreach my $key3 (@list2) {
if ($info->{$key3} !~ /^\(/) {
my @list3 = split(' ', $info->{$key3});
foreach my $key4 (@list3) {
if ($info->{$key4} !~ /^\(/) {
my @list4 = split(' ', $info->{$key4});
foreach my $key5 (@list4) {
$map_data->{$key}->{$key2}->{$key3}->{$key4}->{$key5} = $info->{$key5};
}
}
else {
$map_data->{$key}->{$key2}->{$key3}->{$key4} = $info->{$key4};
}
}
}
else {
$map_data->{$key}->{$key2}->{$key3} = $info->{$key3}
}
}
}
else {
$map_data->{$key}->{$key2} = $info->{$key2};
}
}
}
else {
$map_data->{$key} = $info->{$key};
}
}

return $map_data;
}



the output should look like this:

my $map_data = parse($info);

print Dumper $map_data;


Code
 
$VAR1 = {
'sys_rh_rsync' => {
'sys_rh_rsync__n2' => '(irsync107,-,) (irsync108,-,)',
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_nis3' => {
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)'
},
'sys_rh_rsync__n1' => '(icsl0944,-,) (icsl0945,-,) (icsl2878,-,)'
},
'skl_rtl_users__n56' => '(-,sgluxman,) (-,sgoh9,) (-,sgoldenb,) (-,sgollapu,)',
'coe73_users__n53' => '(-,wwang69,) (-,wwong23,) (-,wwong5,) (-,wwong8,) (-,wwsee,) (-,wyeohx,) (-,wyuan,) (-,xdang,) (-,xiaomin2,)',
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'iclbuild' => '(biur7,-,) (biur9,-,) (biur10,-,) (biur11,-,) (biur12,-,) (biur13,-,)',
'sys_rh_alldisks' => {
'sys_rh_rsync' => {
'sys_rh_rsync__n2' => '(irsync107,-,) (irsync108,-,)',
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_nis3' => {
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)'
},
'sys_rh_rsync__n1' => '(icsl0944,-,) (icsl0945,-,) (icsl2878,-,)'
},
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_backup' => '(iillsbk0100,-,) (iillsbk0101,-,)',
'sys_rh_start' => '(iinf069,-,) (iinf157,-,)'
},
'sys_rh_backup' => '(iillsbk0100,-,) (iillsbk0101,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)',
'sys_rh_rsync__n2' => '(irsync107,-,) (irsync108,-,)',
'skl_rtl_users__n15' => '(-,dbenita,) (-,dbenner,) (-,dbenyose,) (-,dbgurura,)',
'skl_rtl_users__n14' => '(-,csmithhi,) (-,csnguyen,) (-,csnider,) (-,csoni,)',
'sys_rh_nis3' => {
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)'
},
'sys_rh_rsync__n1' => '(icsl0944,-,) (icsl0945,-,) (icsl2878,-,)',
'sys_rh_start' => '(iinf069,-,) (iinf157,-,)',
'skl_rtl_users__n72' => {
'skl_rtl_users__n56' => '(-,sgluxman,) (-,sgoh9,) (-,sgoldenb,) (-,sgollapu,)',
'skl_rtl_users__n15' => '(-,dbenita,) (-,dbenner,) (-,dbenyose,) (-,dbgurura,)',
'sys_triple_group' => '(icsl0945,-,)',
'skl_rtl_users__n14' => '(-,csmithhi,) (-,csnguyen,) (-,csnider,) (-,csoni,)'
},
'sys_ed_all' => {
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_backup' => '(iillsbk0100,-,) (iillsbk0101,-,)',
'sys_rh_start' => '(iinf069,-,) (iinf157,-,)'
},
'sys_triple_group' => '(icsl0945,-,)',
'su_u_av_fc_rel' => '(-,ebenzin1,) (-,nmigdal,)'
};


Any idea?

Thanks,
Zohman.


FishMonger
Veteran / Moderator

Apr 23, 2016, 8:10 AM

Post #2 of 10 (2600 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

Your description of the data and how it should be reorganized is very confusing and the layout of your data structure (before and after) is undecipherable by others without a clear and lengthy explanation, which you do not have.


Quote
The data structure contain machines\users and groups

Those should be what you use as your keys.

Your current values appear to be (based on your description) a list of usernames and/or machine names as a single string. If that's the case, it's a really bad design. It should be an array (reference).


zohman
Novice

Apr 23, 2016, 8:59 AM

Post #3 of 10 (2594 views)
Re: [FishMonger] recursive subroutine for constructing hash [In reply to] Can't Post

$info is a structure of output that i get from 3rd party app.

it will serve me later, from my example lets say i want to check who is in group "sys_rh_nis32",
i'll get "(irserer7,-,) (irsrrt8,-,)", and it's good, but if "sys_rh_nis32" lead to another group or groups?

take a look at "sys_rh_nis3" for example, it contain 2 groups "sys_rh_nis32" and "sys_rh_nis33"
i want it to reorginaze the tree of sys_rh_nis3 to contain them like:


Code
 'sys_rh_nis3' => {  
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)'
},


but also to be able to see sys_rh_nis32\sys_rh_nis33 in the main tree because other groups may using them,
or if i need to pull the users\machines from that group directly.

the end result should look like this:

Code
$VAR1 = {  
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)',
'sys_rh_nis3' => {
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)'
}
}



Quote
Those should be what you use as your keys.


Yes but like i said, it's an output of other resource.

array is out of the question in this scenario.

it's not possible just to look at the code and find a way to make it recursive?
the code is working great, but if i have group that is 6 lvl deep it will stop going deeper.
unless i define more and more "foreach" and "if" for every level.

i hope it make more sense now,
Thanks.


FishMonger
Veteran / Moderator

Apr 23, 2016, 9:20 AM

Post #4 of 10 (2588 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

Are irserer7 and irsrrt8 separate users and what does the - dash represent?

Why is using an array in the hash structure "out of the question"?


FishMonger
Veteran / Moderator

Apr 23, 2016, 9:27 AM

Post #5 of 10 (2585 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

Your sub should fix the data structure in the new hash rather than continuing to build and work with a slightly modified version of the original horrible structure.


zohman
Novice

Apr 23, 2016, 2:13 PM

Post #6 of 10 (2573 views)
Re: [FishMonger] recursive subroutine for constructing hash [In reply to] Can't Post


In Reply To
Are irserer7 and irsrrt8 separate users and what does the - dash represent?

Why is using an array in the hash structure "out of the question"?


oh man,

i do lots of other things with the output.
dashes is useless from your perspective,
i'm dealing with it later in my script so
you can ignore it,


Code
my $info =  { 	'su_u_av_fc_rel'     => '(ebenzin1) (nmigdal)',  
'skl_rtl_users__n72' => 'skl_rtl_users__n14 skl_rtl_users__n15 skl_rtl_users__n56 sys_triple_group',
'skl_rtl_users__n15' => '(dbenita) (dbenner) (dbenyose) (dbgurura)',
'skl_rtl_users__n14' => '(csmithhi) (csnguyen) (csnider) (csoni)',
'skl_rtl_users__n56' => '(sgluxman) (sgoh9) (sgoldenb) (sgollapu)',
'sys_rh_alldisks' => 'sys_rh_backup sys_rh_rsync sys_rh_start sys_triple_group',
'sys_rh_backup' => '(iillsbk0100) (iillsbk0101)',
'sys_rh_rsync' => 'sys_rh_rsync__n1 sys_rh_rsync__n2 sys_triple_group sys_rh_nis3',
'sys_rh_nis3' => 'sys_rh_nis33 sys_rh_nis32',
'sys_triple_group' => '(icsl0945)',
'sys_rh_rsync__n1' => '(icsl0944) (icsl0945) (icsl2878)',
'sys_rh_rsync__n2' => '(irsync107) (irsync108)',
'sys_rh_nis33' => '(sync107) (irsy8)',
'coe73_users__n53' => '(wwang69) (wwong23) (wwong5) (wwong8) (wwsee) (wyeohx) (wyuan) (xdang) (xiaomin2)',
'sys_rh_nis32' => '(irserer7) (irsrrt8)',
'iclbuild' => '(biur7) (biur9) (biur10) (biur11) (biur12) (biur13)',
'sys_rh_start' => '(iinf069) (iinf157)'
};


now it's more readable?

i just want to make sure that if the VALUE inside the $info KEY begin with '('
this VALUE contain objects from X class separated by SPACE
and if not they contain objects from Y class separating by SPACE,
VALUE beginning with '(' is my point of reference here.


Quote
Why is using an array in the hash structure "out of the question"?


i'm calling groups from other input to check the existence of the group in the hash,
but i may use your suggestion with array for the object from X class like:


Code
$VAR1 = {   
'sys_rh_nis32' => [
'(irserer7)',
'(irsrrt8)'
],
'sys_rh_nis33' => [
'(irserer107)',
'(irsy8)'
],
'sys_rh_nis3' => {
'sys_rh_nis32' => [
'(irserer7)',
'(irsrrt8)'
],
'sys_rh_nis33' => [
'(sync107)',
'(irsy8)'
]
}
}


but still this is not gonna resolve my primary question.


FishMonger
Veteran / Moderator

Apr 23, 2016, 2:35 PM

Post #7 of 10 (2569 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

As I see it, the primary problem is the poor design of your data structure.

Based on what you've shown and the unanswered questions of mine and the lack of info on how this data is used, I can't determine which of those parts are machines, groups, or users.

It sounds like your whole script is designed around a poorly structured hash (in this case I'm referring to your $map_data hash ref) and you don't want to fix it because that would mean that you would have to rewrite a large portion of your code. Is that right?


(This post was edited by FishMonger on Apr 23, 2016, 2:40 PM)


FishMonger
Veteran / Moderator

Apr 23, 2016, 2:48 PM

Post #8 of 10 (2565 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

Without a proper understanding of your data and how it's being used, no-one will be able to tell you how to fix your sub to do what you want.


Zhris
Enthusiast

Apr 24, 2016, 12:23 PM

Post #9 of 10 (2546 views)
Re: [zohman] recursive subroutine for constructing hash [In reply to] Can't Post

Its been explained that this is possibly an xy problem and that your input and output data structures might be poorly designed. Nonetheless here is a recursive routine that returns your desired output structure:


Code
use strict; 
use warnings;
use Data::Dumper;

my $ref =
{
'su_u_av_fc_rel' => '(-,ebenzin1,) (-,nmigdal,)',
'skl_rtl_users__n72' => 'skl_rtl_users__n14 skl_rtl_users__n15 skl_rtl_users__n56 sys_triple_group',
'skl_rtl_users__n15' => '(-,dbenita,) (-,dbenner,) (-,dbenyose,) (-,dbgurura,)',
'skl_rtl_users__n14' => '(-,csmithhi,) (-,csnguyen,) (-,csnider,) (-,csoni,)',
'skl_rtl_users__n56' => '(-,sgluxman,) (-,sgoh9,) (-,sgoldenb,) (-,sgollapu,)',
'sys_rh_alldisks' => 'sys_rh_backup sys_rh_rsync sys_rh_start sys_triple_group',
'sys_rh_backup' => '(iillsbk0100,-,) (iillsbk0101,-,)',
'sys_rh_rsync' => 'sys_rh_rsync__n1 sys_rh_rsync__n2 sys_triple_group sys_rh_nis3',
'sys_rh_nis3' => 'sys_rh_nis33 sys_rh_nis32',
'sys_triple_group' => '(icsl0945,-,)',
'sys_rh_rsync__n1' => '(icsl0944,-,) (icsl0945,-,) (icsl2878,-,)',
'sys_rh_rsync__n2' => '(irsync107,-,) (irsync108,-,)',
'sys_rh_nis33' => '(sync107,-,) (irsy8,-,)',
'coe73_users__n53' => '(-,wwang69,) (-,wwong23,) (-,wwong5,) (-,wwong8,) (-,wwsee,) (-,wyeohx,) (-,wyuan,) (-,xdang,) (-,xiaomin2,)',
'sys_rh_nis32' => '(irserer7,-,) (irsrrt8,-,)',
'iclbuild' => '(biur7,-,) (biur9,-,) (biur10,-,) (biur11,-,) (biur12,-,) (biur13,-,)',
'sys_rh_start' => '(iinf069,-,) (iinf157,-,)'
};

print Dumper recurse( $ref );

sub recurse
{
my ( $in, $keys ) = @_;

$in // die 'in required';
$keys //= [ keys %$in ];

my $out = { };

for my $key ( @$keys )
{
my $val = $in->{$key};

if ( $val !~ m/\(/ )
{
my $next_keys = [ split ' ', $val ];

$out->{$key} = recurse( $in, $next_keys );
}
else
{
$out->{$key} = $val;
}
}

return $out;
}


Chris


(This post was edited by Zhris on Apr 24, 2016, 12:24 PM)


zohman
Novice

Apr 24, 2016, 11:26 PM

Post #10 of 10 (2531 views)
Re: [Zhris] recursive subroutine for constructing hash [In reply to] Can't Post

Genius,
sub working as expected.

Thanks A lot Chris,
Zohman.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives