Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Searching and printing complex data structures

by Anonymous Monk
on Apr 10, 2013 at 17:59 UTC ( #1028018=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks,

I have a quite complicated object (for various reason it has to be like this) and by using this example I want to ask how to do to specific tasks. I hope it will be easy to understand.

#Created by using; push @{ $Second{Company}->{Identifier} }, Element;

%Hash -> {Company_A} -> { Identifier_1 } -> One or more 'Elements' e +xample (a, b) -> { Identifier_2 } -> One or more 'Elements' e +xample (b, g) -> { Identifier_3 } -> One or more 'Elements' e +xample (c) -> {Company_B} -> { Identifier_1 } -> One or more 'Elements' e +xample (a) -> { Identifier_2 } -> One or more 'Elements' e +xample (g) -> { Identifier_3 } -> One or more 'Elements' e +xample (x)

1) I want to know how many 'b' elements is there in Company_A. Usually I would use something like map { $Count+= 1 if 'a' eq values %Hash{Company_A}{$_} } values %Hash{Company_A}; but it will only access the first element of each Identifier. How can I write a map command to go through every element?

2) When I need to print this hash I have to look if each identifier has one or more elements (scalar) and fork the prints to print out everything in line by line case (foreach and use count++). Amount of elements vary and there is a lot of data inside so I don't want to create duplicate entries</pp>

scalar () if more than 1 { foreach $Company_A{Identifier_1}[$Count] $Company_A{Identifier_2}[$Count] $Company_A{Identifier_3} $Count++ } if = 1 { $Company_B{Identifier_1} $Company_B{Identifier_2} $Company_B{Identifier_3} } Ouptut: Company_A a, b, c Company_A b, g, c Company_B a, g, x

Some Identifiers have more elements (always equal amount) and other have only one. I need to print the ones with multiple elements separately - they share the elements which only appear once. Because I am doing it for separate objects I was wondering if there is a way to print everything in one block with a single command?

Thanks so much for any tips. Humble apprentice

Replies are listed 'Best First'.
Re: Searching and printing complex data structures
by hdb (Monsignor) on Apr 10, 2013 at 19:22 UTC

    Data::Dumper is a good example how to print a data structure. It is also not difficult to write a recursive sub that does a similar thing. See below. You could also add a callback function that searches for whatever. I made some assumptions about the data structure you are looking at but I think my example is relatively general.

    use strict; use Data::Dumper; my %hash; $hash{Company_A}{ Identifier_1 } = ["a", "b"]; $hash{Company_A}{ Identifier_2 } = ["b", "g"]; + $hash{Company_A}{ Identifier_3 } = "c"; $hash{Company_B}{ Identifier_1 } = "a"; $hash{Company_B}{ Identifier_2 } = "g"; $hash{Company_B}{ Identifier_3 } = "x"; print Dumper(%hash); traverse( 0, \%hash ); sub traverse { my $level = shift; my $ref = shift; if( ref($ref) =~ /HASH/ ) { print "\n"; for my $key (keys %$ref) { print "\t" x $level, $key; traverse( $level+1, $$ref{$key} ); } } elsif( ref($ref) =~ /ARRAY/ ) { print "\n"; for (@$ref) { print "\t" x $level; traverse( $level+1, $_ ); } } else { print "\t" x $level, $ref, "\n"; } }
      I was just thinking to myself that I need something like Data::Dumper :). Cheers
Re: Searching and printing complex data structures
by Cristoforo (Curate) on Apr 10, 2013 at 19:10 UTC
    Using aitap's answer for finding the 'b's in Company_A, (I think the assignment to '()' isn't necessary), I reproduced your output with this code.
    #!/usr/bin/perl use strict; use warnings; use 5.014; use Data::Dumper; my %hash = ( Company_A => { Identifier_1 => ['a', 'b'], Identifier_2 => ['b', 'g'], Identifier_3 => ['c'] }, Company_B => { Identifier_1 => ['a'], Identifier_2 => ['g'], Identifier_3 => ['x'] }); my $b_count = map { grep {$_ eq 'b'} @$_ } values %{ $hash{Company_A} +}; for my $company (sort keys %hash) { my (@ones, @multi); my $href = $hash{$company}; for my $id (sort keys %$href) { my $aref = $href->{$id}; if (1 == @$aref) { push @ones, $aref->[0]; } else { push @multi, $aref; } } if (@multi) { for my $m (@multi) { print "$company ", join(",", @$m, @ones), "\n"; } } else { print "$company ", join(",", @ones), "\n"; } }
    C:\Old_Data\perlp>perl Company_A a,b,c Company_A b,g,c Company_B a,g,x
      OP here. Thanks very much guys, I get the idea and will play around with the code.
Re: Searching and printing complex data structures
by aitap (Curate) on Apr 10, 2013 at 18:22 UTC


    my $b_count = () = map { grep { $_ eq "b" } @$_ } values %{$Hash{Compa +ny_A}};
    This iterates over values of anonymous hash referenced in $Hash{Company_A}, which are anonymous array references, and returns a list of "b" values, which, assigned to a scalar, transforms to the count of the values. Untested, but should work.

    Sorry, I couldn't understand your second question. Perhaps reading perlreftut will help you solving it yourself.

Re: Searching and printing complex data structures
by jethro (Monsignor) on Apr 10, 2013 at 18:24 UTC

    map is simply a loop construct, like foreach(), while() or even grep(). If you have a composite type (like hash or array) you need a loop to get at all values. If you have a composite type inside another composite type (for example a HashofArrays) you obviously need a loop inside a loop aka nested loops. For even higher dimensions you need the corresponding number of nested loop constructs. Right?

    Now you have a HashOfArrays, a composite type of dimension 2, so you need a nested loop. If you want to use map (instead of foreach) then you need a nested map, i.e. a map inside a map. The outer map is for the hash, the inner map is for the array.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1028018]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (1)
As of 2022-07-03 01:58 GMT
Find Nodes?
    Voting Booth?
    My most frequent journeys are powered by:

    Results (103 votes). Check out past polls.