Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

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 romping around the Monastery: (2)
As of 2022-07-05 00:57 GMT
Find Nodes?
    Voting Booth?

    No recent polls found