Thursday, January 6, 2011

Perl:Howto combine two arrays into hash

Hash is basically a double array that consists of keys & values. It's extremely useful when we search for some key that has been assigned with some variable.
For example let's say we have 2 files containing machines names & their serial numbers:

#cat file1
machine01
machine02
machine03

#cat file2
zxvsd
x123a
fsaz1

Now let's say we want to combine this data into one hash table, so whenever we refer to machine01 we will have immediate access to it's serial.
In Perl (v5.xx) the combined hash will look something like this:

#!/usr/bin/perl -w
use strict;
use warnings;
my @arr1=`cat file1`;
my @arr2=`cat file2`;
my %hash;
@hash{@arr1} = @arr2
Now if you iterate over %hash with "foreach" loop such as:
foreach (%hash) {
print "$_\n";
}

You will get:

machine01
zxvsd
machine02
x123a
machine3
fsaz1 
Ok, now when we know the basics let try do something more practical.
Let's say we have 2 huge arrays of machines vs serial numbers, and we
instantly want to find which serial number corresponds to what machine.
We could basically use "foreach" loop, but let's say performance is critical
In such case hash table is our best friend. 
Take a look at the following example:
 
#!/usr/bin/perl

my @machines=("server01","server02","server03");
my @serials=("1111","2222","3333");
 
#Define the hash... 
my %hash;
@hash{@machines}=@serials;

if (exists $hash{$ARGV[0]}) {
   print "Value for $ARGV[0] is: $hash{$ARGV[0]}\n";
 } else {
   print "$ARGV[0] Not found!\n";
 } 
 
What is going on here?
We defined two (short, just for sake of simplicity) arrays.
We defined a hash that combines them, it takes machines (server names)
as keys and serials as values.

Next we expect a user to give input as one argument.
If that argument exists in the hash the script will give output the 
corresponding value, if not it will say that such key wasn't found. 
 
Sample run: 
./hash_check.pl server01
Value for server01 is: 1111
  
./hash_check.pl server_foo
server_foo Not found! 

2 comments:

odoc said...

Excellent post! Just had a quick question:

What if the list of serial numbers is not in order with respect to the the list of machines? How can you assign one specific string in one array to another string in another array? Essentially, I'm looking at comparing the two arrays in a hash by file name.

Cheers!

odoc said...

nvm I figured it out

http://stackoverflow.com/questions/17197915/how-to-assign-two-arrays-to-a-hash-and-correlate-them-by-name-basis-in-perl