views:

219

answers:

4

Hi,

I am looking for a more elegant way to create a hash that contains the list I have read in from my configuration file. Here is my code:

read_config($config_file => my %config);

my $extension_list_reference = $config{extensions}{ext};

my @ext;

# Store each item of the list into an array

for my $i ( 0 .. (@$extension_list_reference - 1) ) {
    $ext[$i] = $extension_list_reference->[$i];
}

# Create hash with the array elements as the keys

foreach my $entry (@ext) {
    $extensions{$entry} = "include";
 }

Thanks.

+5  A: 

Try using map: http://perldoc.perl.org/functions/map.html

Here's what your new code should look like:

my %extensions = map { $_ => "include" } @{ $config{extensions}{ext} };
Neil
Thanks. How's Brooklyn? My birthplace.
Dr. Faust
It's nice, just moved here 4 months ago.
Neil
my %extensions = map { $_ => "include" } @{ $config{extensions}{ext} }
Kent Fredric
Thanks Kent for the refactoring.
Neil
+13  A: 

my %hash = map { $_ => 'include' } @list;

Rhose
The following worked: %extensions = map {$_ => "include" } @$extension_list_reference;
Dr. Faust
+2  A: 

If I understand your problem, this is how you do it in one line:

@extensions{@$extension_list_reference} = ();

Note: each value of the hash is empty, but you still can check whether the key exists in the hash using function exists, like this:

if(exists $extensions{$some_key}) {...

P.S. If by some reason you really need those strings 'include' as values, you can have them, too:

@extensions{@$extension_list_reference} = ('include') x @$extension_list_reference;
Igor Krivokon
Why does this work instead of : %extensions{@$extension_list_reference} = (); ?
Dr. Faust
Because you are operating on a 'hash slice': http://perldoc.perl.org/perldata.html#Slices
Sinan Ünür
Right. Thanks.
Dr. Faust
This works fine when the list has more than one value. It's possible that someone could have only one value in their configuration file. How could I handle one value versus many values?
Dr. Faust
I'm sorry I forgot to include the error message I get if the list contains only one item: Can't use string (".frames") as an ARRAY ref while "strict refs" in use at create_video_frames.pl line 209 (#1) (F) Only hard references are allowed by "strict refs". Symbolic references are disallowed. See perlref.Uncaught exception from user code: Can't use string (".frames") as an ARRAY ref while "strict refs" in use at create_video_frames.pl line 209. at create_video_frames.pl line 209
Dr. Faust
You can check what $extension_list_reference points by using the ref function. So $extension_list_reference = ref $extension_list_reference ? $extension_list_reference : [ $extension_list_reference ]; ought to do it.
Sinan Ünür
Neil, it looks like the problem is in read_config function, and that it works differently when you have just one item - it returns a string instead of a reference. If you don't have access to read_config, you can use the abovementioned trick from Sinan Unur comment.
Igor Krivokon
There are three cases to deal with: one item, more than one items and zero items. Could someone explain this statement: $extension_list_reference = ref $extension_list_reference ? $extension_list_reference : [ $extension_list_reference ]; ref $extension_list_reference will return something like "array", "string" or "undef"?
Dr. Faust
Neil, if read_config() treats all 3 cases consistently, you don't need to worry about ref. It's just a (quick and dirty) workaround; but it's better to fix the problem than create a workaround. Please take a look at your read_config(), at the place where you populate %config hash. The problem should be there.
Igor Krivokon
@raindog I think Neil is using http://search.cpan.org/~dconway/Config-Std-v0.0.4/lib/Config/Std.pm#Multi-part_configuration_values which only returns a list of values if the key appears more than once.
Sinan Ünür
Ouch. Sinan, you're right.Neil, disregard my question, just do what Sinan has proposed. Note: you'll need this workaround with every solution, it has nothing to do with slicing.
Igor Krivokon
I am using Config-Std-v0.0.4. I would like to understand Sinan's workaround. What's the difference between: "$extension_list_reference" and "[ $extension_list_reference ]" ?
Dr. Faust
The operator [] creates a reference to an array. The function read_config() can create either a reference to an array, or just a string. If this is a reference, you don't need to do anything. If this is a string, [ "something" ] will create an array and return a reference to it.
Igor Krivokon
Thanks for the explanation.
Dr. Faust
+2  A: 

This way:

read_config($config_file => my %config);
%extensions = map +($_ => "include"), @{$config{extensions}{ext}};

or this way:

read_config($config_file => my %config);
@extensions{@{$config{extensions}{ext}}} = ("include") x @{$config{extensions}{ext}};
Hynek -Pichi- Vychodil
I like this approach - Thanks.
Dr. Faust