Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Add Hash Key Based on Matching Another Key

by spickles (Scribe)
on Jul 28, 2010 at 14:29 UTC ( [id://851724]=perlquestion: print w/replies, xml ) Need Help??

spickles has asked for the wisdom of the Perl Monks concerning the following question:

I have an array of hashes that contains information about access points (name, mac address, etc.). I need to add serial numbers to this list, and I have to query the controller based on the AP's MAC address since this is a 1:1 relationship (i.e. there should never be MAC duplicates, and each MAC address has a specific corresponding serial number). Once I parse the response from the controller, I pick out the serial number. Now I need to update the AP hash and make sure the serial number gets paired with the element containing the correct MAC address. How can I do this? My only thought is to search the array each time finding the one that matches (using indices) and then use that current index value to update the hash. As an example:

#!c:/perl/bin/perl use strict; use warnings; my @aps; my $new_hash = {}; #Here I pull in a text file and parse it line by line, which I'm #omitting, but it's a while loop that populates the #hash and pushes to the array $new_hash->{'ap_name'} = "AP One"; $new_hash->{'ap_MAC'} = "00:00:00:00:00:00"; $new_hash->{'ap_model'} = "1131"; push (@aps, $new_hash);

So let's say we use the MAC address of all zeros to query the controller for the serial number. Now I have to find the one and only element in my AoH that has that MAC address and add its serial number. My current thinking is to do this:

for my $i (0 .. $#aps) { if $aps[$i]->{'ap_MAC'} eq "00:00:00:00:00:00" { $aps[$i]->{'serial'} = "FTX12345678"; } }

Rather than do an inefficient search that could potentially search the entire array (if it's the last element that matches) is there a more efficient way of directly accessing this matching element?

Regards,
Scott

Replies are listed 'Best First'.
Re: Add Hash Key Based on Matching Another Key
by Ratazong (Monsignor) on Jul 28, 2010 at 14:50 UTC

    What about using a nested hash instead of the array? That will save you the lookup-loop when updating an element...

    my %data; # btw.: never call your structure "data" in "real progra +ms" ;-) my $mac = "11:22:33:55:66:77"; $data{$mac}{ap_name} = "AP one"; $data{$mac}{ap_model} = "1131"; my $mac2 = "00:00:00:00:00:00"; if (exists($data{$mac2}) { $data{$mac2}{serial} = "FTX12345"; }

    HTH, Rata

Re: Add Hash Key Based on Matching Another Key
by moritz (Cardinal) on Jul 28, 2010 at 14:50 UTC
    If you store the hash references not in an array, but in a hash (and keyed by MAC address), you can get rid of the linear scan over the array. If you need to preserve the order, just store two references to each hash, one in the array, one in the hash.
    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Add Hash Key Based on Matching Another Key
by jethro (Monsignor) on Jul 28, 2010 at 14:53 UTC
    That's what hashes are for. First create a hash with the mac address as key and the hash pointer as value (the advantage is you need to do this only once):

    my %macs; foreach @aps { $macs{$_->{'ap_MAC'}}=$_; }

    then your loop is reduced to this:

    $macs{"00:00:00:00:00:00"}{'serial'} = "FTX12345678";

    If you often need to know the array index too, you might store the index number as value into the hash instead of the pointer

      Thanks everyone! Just what I needed.
Re: Add Hash Key Based on Matching Another Key
by zek152 (Pilgrim) on Jul 28, 2010 at 16:12 UTC

    It looks like your question has been answered well. I just wanted to make sure that you were aware that MAC address can be changed and spoofed. As long as that doesn't happen in your system then you will be fine. But realize that if you key with MAC addresses be prepared for that failure mode.

      Thanks zek152. In this case, we're using the burned in MAC of an Access Point, something that's not easily spoofed. Spoofing the MAC of a Linksys router and/or a client laptop wired/wireless is certainly trivial.

      Regards,
      Scott

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://851724]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2024-04-23 21:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found