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

Hey Monks
I have two arrays. One contains command line switches the other contains command line switches followed by values. I want to isolate the values after each switch and assign them to that switch. I also want to assign the values following the next switch and so on for an infinite number of switches.
@switches = ("-d", "-l", "-m"); @values = ("-d", "disk1", "disk2", "disk3", "-l", "load1", "load2", "l +oad3", "load4", "-m" "memory1", "memory2");
So when my program asks what are the values for "l" (switch names decided at run time so it could be anything not just "l", "d"or "m") it should recieve an array containing  ("load1", "load2", "load3", "load4").

I know it has something to do with hashes (probably) but my experience with them is limited.

What would be the best way to implement this?
Thanks in advance

j o h n i r l .

 Sum day soon I'Il lern how 2 spelI (nad tYpe)

Replies are listed 'Best First'.
Re: Creating a Hash from Two Arrays
by Abigail-II (Bishop) on Sep 18, 2002 at 17:15 UTC
    A way to implement this is:
    use strict; use warnings; my @switches = qw /-d -l -m/; my @values = qw /-d disk1 disk2 disk3 -l load1 load2 load3 load4 -m memory1 memory2/; my %switches; @switches {@switches} = (); my $curr; foreach my $v (@values) { if (exists $switches {$v}) { $curr = $v; next; } die "Unknown switch: $v\n" unless defined $curr; push @{$switches {$curr}} => $v; } while (<DATA>) { chomp; $_ = "-$_"; if (exists $switches {$_}) { if ($switches {$_}) { print "Values for $_: @{$switches{$_}}\n"; } else { print "$_ does not have values.\n"; } } else { print "Unknown switch $_\n"; } } __DATA__ l d m x
    This gives:
    Values for -l: load1 load2 load3 load4 Values for -d: disk1 disk2 disk3 Values for -m: memory1 memory2 Unknown switch -x
    Abigail
Re: Creating a Hash from Two Arrays
by zigdon (Deacon) on Sep 18, 2002 at 17:08 UTC
    well, aside from looking at Getopt::Std, you can do something like this:
    my %opts; foreach (@switches) { # init the array for each $opts{$_} = []; } my $curswitch = ''; foreach (@values) { $curswitch = $_ and next if exists $opts{$_}; push @{$opts{$curswitch}}, $_; }
    Untested but should give you an idea. You'll end up with a hash or arrays keyed by the different switches.

    -- Dan

      Some hints on style: your initialization code is rather redundant. This will do the same job:
      my %opts; @opts{@switches} = ([]) x @switches;
      However, due to autovivification you needn't even go through the trouble of assigning those empty lists beforehand. The following will do.
      my %opts; @opts{@switches} = ();
      End of style hints. The following is a slight optimization of the work loop, including switch checking:
      my $curswitch; for (@values) { exists $opts{$_} ? $curswitch = \$opts{$_}, next : die "Unknown switch: $_\n" if /^-/; defined $curswitch or die "Not a switch: $_\n"; push @$curswitch, $_; }

      Makeshifts last the longest.

Re: Creating a Hash from Two Arrays
by fglock (Vicar) on Sep 18, 2002 at 17:05 UTC

    Looks like you need to create a hash of arrays structure:

    my %switches = ( -l => ["load1", "load2", "load3", "load4"], -d => ["disk1", "disk2", "disk3"] ); # add more switches $switches{-m} = ["memory1", "memory2"]; # what's the options for a switch print "-d options are ", join("," => @{$switches{-d}});
Re: Creating a Hash from Two Arrays
by talexb (Chancellor) on Sep 18, 2002 at 17:12 UTC
    Right, you'll probably want to implement this as a hash of arrays. The hash key will be the @switches element, and the resulting data item will be an array of values from your @values array (well, the ones that aren't also in the switches array).
    my %Args; # Hash of arrays for arguments. my $SwitchName; # The current switch name foreach ( @values ) { if ( /^\-/ ) { $SwitchName = $_; else { push ( @{ $Args{ $SwitchName } }, $_ ); } }
    That should produce the data structure that brother fglock mentioned in the first reply.

    --t. alex
    but my friends call me T.

Re: Creating a Hash from Two Arrays
by jmcnamara (Monsignor) on Sep 18, 2002 at 17:14 UTC

    The best thing to do is store the switches in a hash or arrays as follows:
    #!/usr/bin/perl -w use strict; my %switches = ( d => ['disk1', 'disk2', 'disk3'], l => ['load1', 'load2', 'load3'], m => ['memory1', 'memory2'], ); my $switch = 'l'; print @{$switches{$switch}} if exists $switches{$switch};

    --
    John.