I am trying to use the package Normalize, but I have the data in arrays (#x), not in some pointing arrays which the package requires for normalization.
Wanted data format in a pointing array as hash
my %xx = ('1' => 22.595451, '2' => 20.089094, '3' => 17.380813);
Current data format
my #x = qw/22.595451 20.089094 17.380813/;
i.e. ('22.595451', '20.089094', '17.380813').
How can you convert the data to the pointing data-structure?
You can pass your array by reference instead of using a hash. Like this
use strict;
use warnings;
use Normalize;
my #x = qw/ 22.595451 20.089094 17.380813 /;
my $norm = Normalize->new(round_to => 1e-16);
$norm->normalize_to_max(\#x);
print "$_\n" for #x;
which will normalize the contents of #x in place
The actual name for what you call a "pointing array" is a hash, which is a type of associative array.
my %xx; $xx{$_} = $x[$_] for 0..$#x;
-or-
my %xx = map { $_ => $x[$_] } 0..$#x;
That said, Borodin pointed out that that module's functions accept a reference to an array as well as a reference to a hash. That means you don't need to do
my %xx = map { $_ => $x[$_] } 0..$#x;
$norm->normalize_to_max(\%xx);
since you can simply do
$norm->normalize_to_max(\#x);
The easiest way to convert an array into a hash.
my %hash;
#hash{ keys #array } = values #array;
Related
I'm very new to perl. Need some assistance in the below scenario.
I have declared an array and trying to initialize like
my #array1;
$array1[0] = 1;
$array1[1] = 2;
$array1[3] = 4;
Now I want to insert another array lets say my #data = [10,20,30]; at index 2 of array1.
So after insert array1 should look like [1, 2, [10,20,30],4]
How can I do that?
You will need to use array references.
In short you can do
$array1[2] = \#data;
This will make the second member of $array1 a reference to #data. Because this is a reference you can't access it in quite the same way as a normal array. To access #data via array1 you would use #{$array1[2]}. To access a particular member of the reference to #data you can use -> notation. See for example the simple program below:
use strict;
use warnings;
my #array1;
$array1[0] = 1;
$array1[1] = 2;
$array1[3] = 4;
my #data = (10,20,30);
$array1[2] = \#data;
print "A #array1\n"; #Note that this does not print contents of data #data
print "B #{$array1[2]}\n"; #Prints #data via array1
print "C $array1[2]->[0]\n"; #Prints 0th element of #data
You can write
$array1[2] = [10,20,30];
Be aware that what you inserting into the host array is actually an array reference. Hence the syntax: [10,20,30] is a reference while (10,20,30) is a list proper.
Perl doesn't have nested arrays.
You can use splice for doing so.
use Data::Dumper;
splice #array1, 2, 0, #data;
print Dumper \#array1;
the splice prototype is:
splice [origin array], [index], [length of elements to replace], [replacement]
If I have a hash of data from a JSON import, is there a neat way to handle cases where an element could be either a value or an array of values?
So it could be
'blah' => [1,2,3,4,5]
or
'blah' => 1
Can I 'force' blah to be an array, even if it's not, so I can iterate over it and not worry about the number of elements?
I thought I could possibly push the contents of blah onto an empty array which would either push the single value onto the array or join the two arrays together. Is there a neat/best way to do this?
Assuming it will always be either a scalar number or an array reference:
Test, explicitly, if it is a reference. If it is, then assign it back to itself. Otherwise, wrap it in an array reference and assign that instead.
$foo{blah} = (ref $foo{blah}) ? $foo{blah} : [ $foo{blah} ];
It is not clear what you try to achieve, more details with sample code demonstrating the usage would be more helpful
use strict;
use warnings;
use Data::Dumper;
my $debug = 0;
my %hash = ( 'a' => 1,
'b' => [2,3,4,5,6,7,8,9],
'c' => { 'x' => 'one', 'y' => 'two', 'z' => 'three' }
);
print Dumper(\%hash) if $debug;
while( my ($k,$v) = each %hash ){
print "[variable] $k = $v\n" if ref $v eq '';
print "[array ] $k\n", Dumper($v) if ref $v eq 'ARRAY';
print "[hash ] $k\n", Dumper($v) if ref $v eq 'HASH';
}
Please visit following webpage, I believe you will find it useful
I currently have an referenced hash and an array of keys that the hash contains. I want to get an array of the values corresponding to my array of keys.
I know how to do this in multiple lines:
# Getting hash reference and array of keys.
my $hashRef = {
one => 'foo',
two => 'bar',
three => 'baz'
};
my #keys = ('one', 'three');
# Getting corresponding array of values.
my #values;
foreach my $key (#keys) {
push #values, $hashRef->{$key};
}
However, I believe that there must be a much better way that doesn't make use of a loop. But unfortunately I just can't figure it out. How can I efficiently
get an array of values from a referenced hash and an array of keys; ideally in one line if possible?
Easily:
my #values = #$hashRef{#keys};
Or, on Perl 5.24+:
my #values = $hashRef->#{#keys};
Or, on Perl 5.20+ by enabling some additional features:
use feature qw(postderef);
no warnings qw(experimental::postderef);
my #values = $hashRef->#{#keys};
This takes advantage of the fact that you can get the values for multiple keys (a "slice") of a %hash with the #hash{LIST} syntax. You just have to dereference it first. See perldoc for more information.
I'm trying to store an array (not array ref) in a hash but it is treating the array in scalar context and only storing the last value of array in the $hash->{key}.
use Data::Dumper;
$h->{'a'} = ( 'str_1', 'str_2' );
print Dumper $h;
Output: $VAR1 = { 'a' => 'str_2' };
Why can't I store an array in hash-Key and access the array elements as $hash->{key}[index]
$h->{'a'} = [ 'str_1', 'str_2' ];
You can only store scalar as a hash value, and scalar can be simple value or array reference.
Check perldoc.
Values of a hash have to be scalar values, cannot be arrays or hashes. So you need to use array reference as the value of $h->{'a'}:
$h->{'a'} = [ 'str_1', 'str_2' ];
and access them by using
$h->{'a'}->[0]; # for 'str_1'
$h->{'a'}->[1]; # for 'str_2'
By the way, as pointed out by #RobEarl, you also can use the following syntax
$h->{'a'}[0]; # for 'str_1'
$h->{'a'}[1]; # for 'str_2'
See perlref for how to create and use different kind of references.
In an earlier question I asked how to initialize a Perl hash using slices. It is done like this:
my %hash = ();
my #fields = ('currency_symbol', 'currency_name');
my #array = ('BRL','Real');
#hash{#fields} = #array;
Now let's imagine a more complex hash, and here is how it is initialized:
my %hash = ();
my $iso = 'BR';
$hash->{$iso}->{currency_symbol} = 'BRL';
$hash->{$iso}->{currency_name} = 'Real';
print Dumper($hash);
This results in the following:
$VAR1 = {
'BR' => {
'currency_symbol' => 'BRL',
'currency_name' => 'Real'
}
};
Now the question would be: how to initialize this particular hash using the splice method?
The perllol documentation's Slices section covers array slices:
If you want to get at a slice (part of a row) in a multidimensional array, you're going to have to do some fancy subscripting. That's because while we have a nice synonym for single elements via the pointer arrow for dereferencing, no such convenience exists for slices. (Remember, of course, that you can always write a loop to do a slice operation.)
Here's how to do one operation using a loop. We'll assume an #AoA variable as before.
#part = ();
$x = 4;
for ($y = 7; $y < 13; $y++) {
push #part, $AoA[$x][$y];
}
That same loop could be replaced with a slice operation:
#part = #{ $AoA[4] } [ 7..12 ];
Extrapolating to hash slices, we get
#{ $hash{$iso} }{#fields} = #array;
You know it's a hash slice because the “subscripts” are surrounded with curly braces rather than square brackets.
First of all, since your hash is declared %hash, it would just be $hash{ $iso }. $hash->{ $iso } refers to a slot in the hash pointed to by $hash, which may or may not be pointing to %hash.
But once you have that, you can do the following:
#{ $hash{ $iso } }{ #fields } = qw<BRL Real>;
But as levels soon get complex, it's better to forgo the autovivification luxury and do the following:
my $h = $hash{ $iso }{blah}{blah} = {};
#$h{ #field_names } = #field_values;
Relocatable pointers within the hierarchy of hashes makes it easier to write anonymous accesses that also allow for easy slices.
$hash{$iso} is going to be a hash reference. You replace what would be the variable name (without the sigil) in a simple slice with a block containing the reference, so:
#array{#list}
becomes
#{ $hash{$iso} }{#list}
See http://perlmonks.org/?node=References+quick+reference