Solved

combining data structures

Posted on 2009-05-06
19
157 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Perl for loop for 2000 ms 7 98
PHP equivalent of opening a com object 5 83
problem with using the glob function 1 69
perl script to search for files containing text 3 79
Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
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…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.

813 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now