Solved

combining data structures

Posted on 2009-05-06
19
159 Views
Last Modified: 2012-05-06
Guys, I need help on writing a code that will do the following:

1. identify the values of a reference to HoH that are different from a given Hash
Hash -->
my %Line = ('LIST'=>'2','PAGES'=>'77','EDITION'=>'new');

HoH-->
 my $HoH = { 'BOOK1' => {'LIST'=>'2','PAGES'=>'100','EDITION'=>'old'},
'BOOK2' => {'LIST'=>'10','PAGES'=>'77','EDITION'=>'new'},
'BOOK3' => {'LIST'=>'20','PAGES'=>'30','EDITION'=>'old'},
'BOOK4' => {'LIST'=>'2','PAGES'=>'300','EDITION'=>'new'}};

2. create a HoH that will contain these elements
desired output:
  my $HoH = { 'BOOK1' => {'PAGES'=>'100','EDITION'=>'old'},
                       'BOOK2' => {'LIST'=>'10'},
                       'BOOK3' => {'LIST'=>'20','PAGES'=>'30','EDITION'=>'old'},
                       'BOOK4' => {'PAGES'=>'300'}};

3. print with the following format:
1. BOOK1 (PAGES:100, EDITION:old)                                   2. BOOK2 (LIST:10)
3. BOOK3 (LIST:20, PAGES:30, EDITION:old)                       4. BOOK4 (PAGES:300)

I'd greatly appreciate it someone could help me out with this. Thanks in advance!!!!
0
Comment
Question by:cucugirl
  • 9
  • 8
  • 2
19 Comments
 
LVL 39

Accepted Solution

by:
Adam314 earned 500 total points
ID: 24316128
Wasn't sure if you wanted to change your original $HoH, or make a new.  This first makes a copy of $HoH to $HoH2, then changes that.  If you want to change your original $HoH, just replace $HoH2 with $HoH, and remove the dclone line.
use Storable 'dclone';
 
my %Line = ('LIST'=>'2','PAGES'=>'77','EDITION'=>'new');
 
my $HoH = {'BOOK1' => {'LIST'=>'2','PAGES'=>'100','EDITION'=>'old'},
           'BOOK2' => {'LIST'=>'10','PAGES'=>'77','EDITION'=>'new'},
           'BOOK3' => {'LIST'=>'20','PAGES'=>'30','EDITION'=>'old'},
           'BOOK4' => {'LIST'=>'2','PAGES'=>'300','EDITION'=>'new'}};
 
##### This line makes a copy of $HoH
my $HoH2=dclone($HoH);
 
##### This removes key/value pairs from $HoH2
foreach my $book (keys %$HoH2) {
	foreach my $key (keys %{$HoH2->{$book}}) {
		next if $HoH2->{$book}->{$key} ne $Line{$key};
		delete $HoH2->{$book}->{$key};
	}
}
 
##### This displays them
my $count=0;
foreach my $book (sort keys %$HoH2) {
	$count++;
	printf '%-50s', "$book (" . join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}}) . ")";
	print "\n" unless ($count % 2);
}

Open in new window

0
 

Author Comment

by:cucugirl
ID: 24318713
Adam, now that I just notice the possibility of $HoH2 being empty is there a way to print this:

book1

rather than:

book1()

thanksssss for all your help! :)
0
 
LVL 39

Expert Comment

by:Adam314
ID: 24326491

##### This displays them
my $count=0;
foreach my $book (sort keys %$HoH2) {
    $count++;
    my $attr=join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}});
    printf '%-50s', "$book" . ($attr ? " ($attr)" : "");
    print "\n" unless ($count % 2);
}

Open in new window

0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

Author Comment

by:cucugirl
ID: 24344088
question... I don't have dclone, use storage in my PERL version, is there another way to copy this hash so that the original one is not affected? thanks!
0
 
LVL 84

Expert Comment

by:ozo
ID: 24344459
#if $HoH is known to be exactly 2 deep, you might do

my $HoH2={map{$_=>{%$HoH->{$_}}}keys %$HoH};
0
 
LVL 84

Expert Comment

by:ozo
ID: 24344545
#or in one step

my $HoH2={
      map{
        my$book=$HoH->{$_};
        $_=>{
            map{
                $_ => $book->{$_}
            }
            grep{
                $book->{$_} ne $Line{$_}
            }
            keys %$book
        }
      }keys %$HoH
    };
0
 

Author Comment

by:cucugirl
ID: 24344559
thanks ozo! question... I'd like to use $_ as least as possible... how can reduce the amount of $_ in that loop? thanks!!
0
 
LVL 84

Expert Comment

by:ozo
ID: 24344681
my $HoH2={
      map{
          my $book=$_;
          my $hash=$HoH->{$book};
          my %new=();
          for $key ( keys%$hash ){
              $new{$key}=$hash->{$key} if  $hash->{$key} ne $Line{$key}
          }
          $book=>{%new}
       }keys %$HoH
    };
0
 
LVL 84

Expert Comment

by:ozo
ID: 24344870
my $HoH2;
while( my($book,$hash) = each %$HoH  ){
          my %new=();
          for my $key ( keys%$hash ){
              $new{$key}=$hash->{$key} if  $hash->{$key} ne $Line{$key}
          }
          $HoH{$book} = {%new};
};
0
 

Author Comment

by:cucugirl
ID: 24345016
ok got it! thankssss! question.. why would copying it directly affect the original one in this case? if I have the following
@array2 = [1,2,3];
@array1 = @array2;
and do something to @array1 nothing will happen to @array2.. but why in this case do I have to copy it like this? I want to make sure I understand why the original element is being affected with this code..

thanks!
0
 
LVL 84

Expert Comment

by:ozo
ID: 24345757
did you mean
@array2 = (1,2,3);
?

@array2 = [1,2,3];
would mean that @array2 has a single element with $array2[0] being a reference to a list of 3 elements.
If you meant that, it would have been better to write it as
@array2 = ([1,2,3]);
or
$array2[0] = [1,2,3];
0
 

Author Comment

by:cucugirl
ID: 24345906
ozo thanks for your help! :)

##### This displays them
my $count=0;
foreach my $book (sort keys %$HoH2) {
      $count++;
      printf '%-50s', "$book (" . join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}}) . ")";
      print "\n" unless ($count % 2);
}

this piece of code will display both columns:
1. BOOK1 (PAGES:100, EDITION:old)                                   2. BOOK2 (LIST:10)
3. BOOK3 (LIST:20, PAGES:30, EDITION:old)                       4. BOOK4 (PAGES:300)

is it possible to just add one line in this code to make it smart enough to do the following:
1. BOOK1 (PAGES:100, EDITION:old)                                   2. BOOK2 (LIST:10)
3. BOOK3 (LIST:20, PAGES:30, EDITION:old, PAGES:100, YEAR:1990)
4. BOOK4 (PAGES:300)

if the content inside of the parenthesis, then just print the next element in another line? thanks in advance for the help!

0
 

Author Comment

by:cucugirl
ID: 24345911
if the content inside of the parenthesis is too much, then just print the next element in another line? thanks in advance for the help!
0
 
LVL 84

Expert Comment

by:ozo
ID: 24345951
my $content =  printf '%-50s', "$book (" . join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}}) . ")";
$count = 0 if length $content > 50;
print $content;
print "\n" unless ($count % 2);

#that should probably be a different question, since it's not really germane to the original question
0
 
LVL 84

Expert Comment

by:ozo
ID: 24345957
#sorry
my $content =  sprintf '%-50s', "$book (" . join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}}) . ")";
0
 

Author Comment

by:cucugirl
ID: 24349104
##### This displays them
my $count=0;
foreach my $book (sort keys %$HoH2) {
    $count++;
    my $attr=join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}});
    printf '%-50s', "$book" . ($attr ? " ($attr)" : "");
    print "\n" unless ($count % 2);
}

my $attr=join(", ", map {"$_:$HoH2->{$book}->{$_}"} keys %{$HoH2->{$book}});
one last question.. in this line: how can I only print the value? rather than the key:value? thanks!
0
 

Author Comment

by:cucugirl
ID: 24349184
also ozo.. in this snippet what do you mean by $line{$new}?

my $HoH2;
while( my($book,$hash) = each %$HoH  ){
          my %new=();
          for my $key ( keys%$hash ){
              $new{$key}=$hash->{$key} if  $hash->{$key} ne $Line{$key}
          }
          $HoH{$book} = {%new};
};
0
 
LVL 84

Expert Comment

by:ozo
ID: 24349487
my $attr=join(", ",  keys %{$HoH2->{$book}});

where do you see $line{$new}?
0
 

Author Comment

by:cucugirl
ID: 24350008
             $new{$key}=$hash->{$key} if  $hash->{$key} ne $Line{$key}
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SIMPLE Perl Regex 1 162
Perl for loop for 2000 ms 7 105
Check only file date not subfolder date before getting folder path 3 80
Export Variables in Perl 3 85
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question