Store excel data in an array of hashes - arrays

My table structure is :
Name Address
Deepti 1325
Cizwan 324
rikita 567
I have to make array like [{Name->deepti,Address->1325},{Name->Cizwan,Address->324},{Name->Rikita,Address->567}]
The table is in excel data, so multiple rows are there.
Thanks in Advance. I have tried something but not able to proceed.
for my $row_num (2..($max_rows))
{
if(exists $workbook->{'cell'}[1][1])
{
#insert values in the hash
$id1 = $workbook->{'cell'}[1][1];
my $val1 = $workbook->{'cell'}[1][$row_num];
#push values in hash
push (#{$hash1{$id1}},$val1);
}
if(exists $workbook->{'cell'}[2][1])
{
#insert values in the hash
$id2 = $workbook->{'cell'}[2][1];
my $val1 = $workbook->{'cell'}[2][$row_num];
#push values in hash
push (#{$hash2{$id2}},$val1);
}
}
print Dumper \%hash1;
print Dumper \%hash2;

So with your structure, you're looking like an array of anonymous hashes is what you want.
This is simpler than you might think:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my #rows;
chomp ( my #header = split ' ', <DATA> );
while ( <DATA> ) {
chomp;
my %row;
#row{#header} = split;
push #rows, \%row;
}
print Dumper \#rows;
__DATA__
Name Address
Deepti 1325
Cizwan 324
rikita 567
This outputs:
$VAR1 = [
{
'Address' => '1325',
'Name' => 'Deepti'
},
{
'Name' => 'Cizwan',
'Address' => '324'
},
{
'Address' => '567',
'Name' => 'rikita'
}
];
But fitting it into your code - you might want to:
push ( #rows, { Name => $id2, Address => $val } );
This works because putting values in {} like that causes it to return an anonymous hash, which you can then insert into the array.

Related

Iterative Hash Set up

I have the following array...
my #array=("100 2", "300 1", "200 3");
From this array I want to iteratively construct a hash.
Current Script:
my %hash;
foreach (#array) {
my #split = (split /\s+/, $_);
%hash = ("$split[0]", "$split[1]");
}
Current Output:
$VAR1 = {
'200' => '3'
};
This is not what I want. My goal is...
Goal Output:
$VAR1 = {
'100' => '2'
'300' => '1'
'200' => '3'
};
What do I need to do?
I am using: Perl 5, Version 18
Assigning to a hash—something you are doing each pass of the loop—replaces its contents. Replace
%hash = ("$split[0]", "$split[1]");
with
$hash{$split[0]} = $split[1];
Alternatively, replace everything with
my %hash = map { split } #array;

Perl: How to access Array of Hashes passed to a Subroutine

Have a perl script reading from an xml, parsing the data into hashes in one sub, outputting an array of hashes and then from main calling a second sub to process the array of hashes.
Data::Dumper shows that everything is being passed properly.
Having a terrible time figuring out why I can't now access the hashes.
use strict;
use warnings;
use Data::Dumper;
my (#sortedData, $value1, $value2);
use subs qw(processData outputData);
#sortedData = processData;
outputData($value1, $value2, \#sortedData);
sub processData{
# Example code
# # Does some processing of xml that results in a hash.
# # That series of hashes is pushed onto an array
my ($item, #results);
# foreach $item ( #{ $rss->{items}){
# my %data = (
# 'first' => $item->{'value'},
# 'second' => $item->{'value'},
# 'third' => $item->{'value'}
# );
# push #results, \%data;
# }
# Essentially the hash is :
#results = (
{'data1'=>810,'data2'=>153,'data3'=>215},
{'data1'=>160,'data2'=>220,'data3'=>604},
{'data1'=>940,'data2'=>103,'data3'=>115},
{'data1'=>100,'data2'=>319,'data3',525},
{'data1'=>500,'data2'=>803,'data3'=>650}
);
return #results;
}
sub outputData{
my ($input1, $input2, #localData) = #_;
print Dumper #localData;
print "\#localData: " . #localData . "\n";
foreach my $i (#localData){
# foreach my $j ($i){
# print $i . "\n" . $j . "\n";
# }
print "\$i: " . $i . "\n";
}
}
The output:
$VAR1 = [
{
'data3' => 215,
'data2' => 153,
'data1' => 810
},
{
'data3' => 604,
'data2' => 220,
'data1' => 160
},
{
'data2' => 103,
'data3' => 115,
'data1' => 940
},
{
'data1' => 100,
'data3' => 525,
'data2' => 319
},
{
'data1' => 500,
'data3' => 650,
'data2' => 803
}
];
#localData: 1
$i: ARRAY(0x80071b30)
I don't understand why the value of #localData is 1 or why the reference for an element of #localData is ARRAY instead of HASH.
I am certainly testing my deeper understanding of PERL arrays for the first time.
I don't understand it as much as I thought.
You pass a reference to the array to the sub, then assign this single scalar to #localData. Fix:
sub outputData{
my ($input1, $input2, $localData) = #_;
print Dumper $localData;
print "\#localData: " . #$localData . "\n";
foreach my $i (#$localData){
...
}
}

Perl multi hash from list

I have a list with some values which are connected. I need to create a hashmap with keys and values from the list and merge together. But i don't really know how to do it.
Input:
my #in =(
'mgenv/1_2_3/parent.dx_environment',
'mgenv/1_2_3/doc/types.dat');
Expected output:
"{ $env => { $ver => [ $file1, $file2, ... ] } }"
I've tried these:
(1)
my #sack_files = (
'mgenv/1_2_3/parent.dx_environment',
'mgenv/1_2_3/doc/types.dat');
my $sack_tree = {};
my %hash=();
for( my $i=0; $i<scalar #sack_files; $i++){
my #array = split(/[\/]+/,$sack_files[$i]);
for(my $i=0;$i<(scalar #array)-1;$i++){
my $first = $array[$i];
my $second = $array[$i+1];
$hash{$first}=$second;
}
# merge
}
(2)
use Data::Dumper;
my #sack_files = (
'mgenv/1_2_3/parent.dx_environment',
'mgenv/1_2_3/doc/types.dat',
);
my $sack_tree = {};
my %hash=();
for( my $i=0; $i<scalar #sack_files; $i++){
my #array = split(/[\/]+/,$sack_files[$i]);
nest(\%hash,#array);
}
In the second case I get an error because when the loop variable i=1 ,the key/values already exists so maybe i have to check the previously added key/values. But I don't really know how.
I would really appreciate any ideas.
Just use push to add new members to an existing array in a hash of hashes. You have to dereference the array reference with #{ ... }.
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my #sack_files = qw( mgenv/1_2_3/parent.dx_environment
mgenv/1_2_3/doc/types.dat
mgenv/1_2_3/doc/etc.dat
mgenv/4_5_6/parent.dx_environment
mgenv/4_5_6/doc/types.dat
u5env/1_2_3/parent.dx_environment
u5env/1_2_3/doc/types.dat
u5env/4_5_6/parent.dx_environment
u5env/4_5_6/doc/types.dat
);
my %hash;
for my $sack_file (#sack_files) {
my ($env, $ver, $file) = split m{/}, $sack_file, 3;
push #{ $hash{$env}{$ver} }, $file;
}
print Dumper \%hash;
output
$VAR1 = {
'mgenv' => {
'1_2_3' => [
'parent.dx_environment',
'doc/types.dat',
'doc/etc.dat'
],
'4_5_6' => [
'parent.dx_environment',
'doc/types.dat'
]
},
'u5env' => {
'4_5_6' => [
'parent.dx_environment',
'doc/types.dat'
],
'1_2_3' => [
'parent.dx_environment',
'doc/types.dat'
]
}
};

Generating a unordered list hash from a array

I am trying to use hashes to generate an unordered list that i can further use in a jstree. But this array has to be generated only from an array that has been passed thru .
my #array = ( "New Order","Recurring Order","Previously Cancelled Order");
I want the output to look something like
$data = {
"New Order" => {
"Recurring Order" =>{
Previously cancelled Order = 1
}
}
};
I can simply do
my $data{$array[0]}{$array[1]}{$array[2]} = 1
but the array can be of n variables, so it becomes a bit more complicated than that. I am thinking of recursion, but i have been sitting here for the last hour trying to figure that out
This will generate the data structure as you have defined it. Not sure why you'd want it though.
my #input = ( "New Order","Recurring Order","Previously Cancelled Order");
my $data = 1;
$data = {$_ => $data} for reverse #input;
use Data::Dump;
dd $data;
If you're just wanting to randomize your array, then use List::Util;
use List::Util qw(shuffle);
my #newOrder = shuffle #input;
sub recursive {
my $v = shift #_;
return #_>1 ? { $v => recursive(#_) } : { $v => #_ };
}
my #array = ( "New Order","Recurring Order","Previously Cancelled Order");
use Data::Dumper; print Dumper recursive(#array, 1);
output
$VAR1 = {
'New Order' => {
'Recurring Order' => {
'Previously Cancelled Order' => 1
}
}
};

Hashes array elements copy

My array of hashes:
#cur = [
{
'A' => '9872',
'B' => '1111'
},
{
'A' => '9871',
'B' => '1111'
}
];
Expected result:
#curnew = ('9872', '9871');
Any simple way to get only the values of the first hash element from
this and assign it to an array?
Mind that hashes are unordered, so I take the word first to mean lexicographically first.
map { # iterate over the list of hashrefs
$_->{ # access the value of the hashref
(sort keys $_)[0] # … whose key is the first one when sorted
}
}
#{ # deref the arrayref into a list of hashrefs
$cur[0] # first/only arrayref (???)
}
The expression returns qw(9872 9871).
Assigning an arrayref to an array as in #cur = […] is probably a mistake, but I took it at face value.
Bonus perl5i solution:
use perl5i::2;
$cur[0]->map(sub {
$_->{ $_->keys->sort->at(0) }
})->flatten;
The expression returns the same values as above. This code is a bit longer, but IMO more readable because the flow of execution goes strictly from top to bottom, from left to right.
First your array have to be defined as
my #cur = (
{
'A' => '9872',
'B' => '1111'
},
{
'A' => '9871',
'B' => '1111'
}
);
Note the parenthesis
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);
my #cur = (
{
'A' => '9872',
'B' => '1111'
},
{
'A' => '9871',
'B' => '1111'
}
);
my #new;
foreach(#cur){
push #new, $_->{A};
}
dump #new;
use Data::Dumper;
my #hashes = map (#{$_}, map ($_, $cur[0]));
my #result = map ($_->{'A'} , #hashes);
print Dumper \#result;

Resources