pruthvik has asked for the wisdom of the Perl Monks concerning the following question:

HI Monks,

I'm trying to create the hierarchy pattern from the input below

Input:

+ instreg@d1@d1 instreg@d1@d2 instreg@d2@d1 instreg@d3@d1 instreg@d4@d1 instreg@d5@d1 instreg@d6@d1 instreg@d7@d1 instreg@d8@d1 alureg@d1@d1 alureg@d2@d1 alureg@d3@d1 alureg@d4@d1 alureg@d5@d1 alureg@d6@d1 alureg@d7@d1 alureg@d8@d1 pgmctr@d1@d1 pgmctr@d2@d1 pgmctr@d3@d1 pgmctr@d4@d1 pgmctr@d5@d1 pgmctr@m1 pgmctr@m2 pgmctr@m3 pgmctr@m4 pgmctr@m5

output:

instreg { d1 { d1,d2 } d2 { d1 } .... ,,, d8 { d1 } } alureg { d1 { d1 } d2 }

Replies are listed 'Best First'.
Re: creating the hierarchy pattern from the input file
by LanX (Saint) on Sep 16, 2021 at 11:40 UTC
    Just for fun:

    use strict; # https://perlmonks.org/?node_ +id=11136806 use warnings; # creating the hierarchy patte +rn from the input file use Data::Dump qw/pp dd/; my $tree ={}; while ( my $line =<DATA> ) { chomp $line; my @keys = split /@/, $line; my $ref = $tree; $ref = ( $ref->{$_} //= {} ) # descend into hashrefs, init +explicitly when missing for @keys } my $out = pp $tree; # now "d1 => { d1 => {} }," et +c # purge $out =~ s/\Q => {}//g; # ... empty hashes $out =~ s/\Q => / /g; # ... fat arrows $out =~ s/\Q},/}/g; # ... trailing commas print $out; __DATA__ instreg@d1@d1 instreg@d1@d2 instreg@d2@d1 instreg@d3@d1 instreg@d4@d1 instreg@d5@d1 instreg@d6@d1 instreg@d7@d1 instreg@d8@d1 alureg@d1@d1 alureg@d2@d1 alureg@d3@d1 alureg@d4@d1 alureg@d5@d1 alureg@d6@d1 alureg@d7@d1 alureg@d8@d1 pgmctr@d1@d1 pgmctr@d2@d1 pgmctr@d3@d1 pgmctr@d4@d1 pgmctr@d5@d1 pgmctr@m1 pgmctr@m2 pgmctr@m3 pgmctr@m4 pgmctr@m5

    OUTPUT:
    -*- mode: compilation; default-directory: "d:/tmp/pm/" -*- Compilation started at Thu Sep 16 13:39:54 C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/text_to_tree.pl { alureg { d1 { d1 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } d6 { d1 } d7 { d1 } d8 { d1 } } instreg { d1 { d1, d2 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } d6 { d1 } d7 { d1 } d8 { d1 } } pgmctr { d1 { d1 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } m1, m2, m3, m4, m5, } } Compilation finished at Thu Sep 16 13:39:55

    alternatively

    use Data::Dumper (which is core) and change the settings for => ("Pair") and so on. See https://metacpan.org/pod/Data%3A%3ADumper#Configuration-Variables-or-Methods

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    update

    added more comments to code

      Hi LanX

      what can be used instead of use "Data::Dump qw/pp dd/;"

        See LanX's comments at the end of the post on using the core Data::Dumper module.


        Give a man a fish:  <%-{-{-{-<

Re: creating the hierarchy pattern from the input file
by tybalt89 (Monsignor) on Sep 16, 2021 at 10:04 UTC

    Well, here's a best guess...

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11136806 use warnings; my %hash; while( <DATA> ) { chomp; my $code = s/\@/}{/gr; eval "\$hash{$code}++"; } #use Data::Dump 'dd'; dd \%hash; sub nest { my $h = shift; my $answer = ''; if( ref $h ) { for my $k ( sort keys %$h ) { $answer .= ref( $h->{$k} ) ? "$k {\n" . nest( $h->{$k} ) =~ s/^/\t/gmr . "}\n" : $k . "\n"; } } $answer; } local $_ = nest \%hash; s/\w\K\n\s*(?=\w)/,/g; print; __DATA__ instreg@d1@d1 instreg@d1@d2 instreg@d2@d1 instreg@d3@d1 instreg@d4@d1 instreg@d5@d1 instreg@d6@d1 instreg@d7@d1 instreg@d8@d1 alureg@d1@d1 alureg@d2@d1 alureg@d3@d1 alureg@d4@d1 alureg@d5@d1 alureg@d6@d1 alureg@d7@d1 alureg@d8@d1 pgmctr@d1@d1 pgmctr@d2@d1 pgmctr@d3@d1 pgmctr@d4@d1 pgmctr@d5@d1 pgmctr@m1 pgmctr@m2 pgmctr@m3 pgmctr@m4 pgmctr@m5

    Outputs:

    alureg { d1 { d1 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } d6 { d1 } d7 { d1 } d8 { d1 } } instreg { d1 { d1,d2 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } d6 { d1 } d7 { d1 } d8 { d1 } } pgmctr { d1 { d1 } d2 { d1 } d3 { d1 } d4 { d1 } d5 { d1 } m1,m2,m3,m4,m5 }

    If this is not what you are looking for, please show the exact output you want, especially for pgmctr, which as LanX has pointed out, has an array/hash conflict.

    P.S. This is also sure to upset the 'eval' haters :)

      > P.S. This is also sure to upset the eval haters :)

      Trouble is rather that you might end with a bug depending on input if you try increment a hashref.

      I would prefer

      DB<41> $ref= $tree DB<42> x @keys = split /@/,'a@b@c' 0 'a' 1 'b' 2 'c' DB<43> $ref = ($ref->{$_}//={})for @keys DB<44> x $tree 0 HASH(0xaa630cf0) 'a' => HASH(0xaa6204a0) 'b' => HASH(0xaa6719b0) 'c' => HASH(0xaa75baa0) empty hash DB<45>

      Update
      And so on for each line
      DB<45> x @keys = split /@/,'a@b@d' 0 'a' 1 'b' 2 'd' DB<46> $ref= $tree <= ($ref->{$_}//={})for @keys DB<48> x $tree 0 HASH(0xaa630cf0) 'a' => HASH(0xaa6204a0) 'b' => HASH(0xaa6719b0) 'c' => HASH(0xaa75baa0) empty hash 'd' => HASH(0xaa672e30) empty hash DB<49>

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      I'm not an eval hater but this is prone to injections.

      (OTOH is vulnerable code maybe the best solution for people abusing the monastery as code writing service. ;)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        > maybe the best solution for people abusing the monastery as code writing service ;)

        Yes, this seems to be getting worse lately!

        I'm reminded of Ian Phillipps' little perl program-generator of 1990. All it did was ask you to enter the program you wanted written ... then post to comp.lang.perl with a title of "I don't think perl can $program_you_wanted_written". In those days, there were plenty of Perl zealots eager to prove that Perl could indeed do it! :) (Mentioned at The Lighter Side of Perl Culture (Part I): Introduction).

      P.S. This is also sure to upset the 'eval' haters :)

      Data::Diver

      Yes this is the expected output , can you also suggest as if the input was a part of a file where to pass the file handle for further processing

      Thanks

        Here's an updated version using ideas stolen borrowed from LanX.

        It sounds like the provided input might be a section of a larger file. If so, you could either pass in the section as a string and use the reference open as shown, or pass in the file handle ($fh) and also specify some input line that will cause a return to caller.

        #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11136806 use warnings; my $inplacefile = <<'END'; instreg@d1@d1 instreg@d1@d2 instreg@d2@d1 instreg@d3@d1 instreg@d4@d1 instreg@d5@d1 instreg@d6@d1 instreg@d7@d1 instreg@d8@d1 alureg@d1@d1 alureg@d2@d1 alureg@d3@d1 alureg@d4@d1 alureg@d5@d1 alureg@d6@d1 alureg@d7@d1 alureg@d8@d1 pgmctr@d1@d1 pgmctr@d2@d1 pgmctr@d3@d1 pgmctr@d4@d1 pgmctr@d5@d1 pgmctr@m1 pgmctr@m2 pgmctr@m3 pgmctr@m4 pgmctr@m5 END my $filename = \$inplacefile; # FIXME change to filename with no refer +ence open my $fh, '<', $filename or die $!; # FIXME improve error message my $hash = {}; while( <$fh> ) { my $ref = $hash; $ref = $ref->{$_} //= {} for split /\@|\n/; } #use Data::Dump 'dd'; dd $hash; sub nest { my $h = shift; join '', map { %{$h->{$_}} ? "$_ {\n" . nest( $h->{$_} ) =~ s/^/\t/gmr . "}\n" : +"$_\n"; } sort keys %$h; } print nest($hash) =~ s/\w\K\n\s*(?=\w+$)/,/gmr;

        Same output as before.

        atta man! that's how you advance the state-of-the-art!

Re: creating the hierarchy pattern from the input file
by The Perlman (Scribe) on Sep 16, 2021 at 08:18 UTC
    So whatt you want to do is:

  • Loop over the input ,
  • split each line on '@',
  • built a tree of nested hashes with arrays as leaves
  • like push @{ hash{instreg}{d1} }, 'd1'

    ???

    UPDATED: So what's your code so far and where are you stuck?

    - Ron
      > built a tree of nested hashes with arrays as leaves

      That's not possible, because the input has varying depth causing conflicts.

      One parent level can't be hash and array at the same time.

      And hashes can't have duplicate keys. So maybe he rather wants nested arrays?

      If the OP didn't show code, then he should at least have shown valid target data.

      Update

      Or maybe the OP doesn't want data but just text displaying a tree?

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      Hi Ron,

      Yes but the array length keeps changing , so how do we consider that ?

      The expectation is the last element should be the value and all other elements should be the keys to each other , and also is there should be no repetition of the keys it should dbe uniq

      Thanks

        "and also is there should be no repetition of the keys it should dbe uniq"

        What?

        - Ron