?
Solved

combining data structures

Posted on 2009-05-06
19
Medium Priority
?
162 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
  • 2
19 Comments
 
LVL 39

Accepted Solution

by:
Adam314 earned 2000 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
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 …
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…
Six Sigma Control Plans
Suggested Courses

741 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