|
List Info
Thread: Re: Transforming a list into a hash of arrays
|
|
| Re: Transforming a list into a hash of
arrays |
  United States |
2007-02-07 18:36:03 |
--- In perl-beginner@yahoogroups.com, Rob Biedenharn
<Rob ...> wrote:
>
>
> On Feb 7, 2007, at 10:58 AM, jslay77 wrote:
>
> > I hope this is the appropriate forum to ask this
question.
> >
> > assume I have a list like this:
> >
> > input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3', '2',
> > 'hostname10', '2', 'hostname11', '3',
'hostname12');
> >
> > I want to turn this list into a hash of anonymous
arrays...something
> > like this I guess.
> >
> > %hash = (
> > '1' => ['hostname1', 'hostname2',
'hostname3'],
> > '2' => ['hostname10', 'hostname11'],
> > '3' => ['hostname12'],
> > );
> >
> >
> >
> >
> > I hope I explained that appropriately.
> > regards,
> > J
>
> Why don't you post some code showing your attempt and
then we can
> help you if it doesn't do what you expect? Here's a
hint, to
> initialize a hash element with an empty array if it
doesn't already
> have a value, you can do this:
>
> $hash{$key} ||= [];
>
> I made a subroutine "array_to_hash" taking a
list of values and
> returning a hash. My little script also used
> List::MoreUtils::natatime to get the pairs from the
array, but that's
> not the only way. I also used Data: umper to
produce the output to
> visually check the result like this:
>
>
> input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3', '2',
> 'hostname10', '2', 'hostname11', '3',
'hostname12');
>
> my %hash = array_to_hash input;
>
> print Data: umper-&g
t;Dump([ input, %hash], [qw(*input *hash)]);
>
> input = (
> '1',
> 'hostname1',
> '1',
> 'hostname2',
> '1',
> 'hostname3',
> '2',
> 'hostname10',
> '2',
> 'hostname11',
> '3',
> 'hostname12'
> );
> %hash = (
> '1' => [
> 'hostname1',
> 'hostname2',
> 'hostname3'
> ],
> '3' => [
> 'hostname12'
> ],
> '2' => [
> 'hostname10',
> 'hostname11'
> ]
> );
>
> -Rob
>
> Rob Biedenharn http://agileconsultingl
lc.com
> Rob ...
>
Rob,
Thanks for the quick response...and your $hash{$key} ||=[]
hint
I actually got around this whole thing by retrieving my data
differently from DBD::Oracle,
however I was still intrigued at the problem...I believe I
figured it out with your help.
This does what I was looking for, however would there be a
better way?
input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3', '2', 'hostname10', '2',
'hostname11', '3', 'hostname12');
my %hash;
my %seen;
my $key;
for ( input; $i <= $#input; $i += 2) {
if (! $seen{$input[$i]}++ ) {
$hash{$input[$i]} ||= ["$input[$i + 1]"];
} else {
push {$hash{$input[$i]}}, $input[$i + 1];
next;
}
}
foreach (sort keys %hash) {
print "$_ --> {$hash{$_}}n";
}
Unsubscribing info is here: h
ttp://help.yahoo.com/help/us/groups/groups-32.html
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://g
roups.yahoo.com/group/perl-beginner/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http
://groups.yahoo.com/group/perl-beginner/join
(Yahoo! ID required)
<*> To change settings via email:
mailto:perl-beginner-digest@yahoogroups.com
mailto:perl-beginner-fullfeatured@yahoogroups.com
<*> To unsubscribe from this group, send an email to:
perl-beginner-unsubscribe@yahoogroups.com
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.c
om/info/terms/
|
|
| Re: Re: Transforming a list into a hash
of arrays |
  United States |
2007-02-07 19:24:07 |
On Feb 7, 2007, at 7:36 PM, jslay77 wrote:
> --- In perl-beginner@yahoogroups.com, Rob Biedenharn
<Rob ...> wrote:
>> On Feb 7, 2007, at 10:58 AM, jslay77 wrote:
>>> I hope this is the appropriate forum to ask
this question.
>>>
>>> assume I have a list like this:
>>>
>>> input = ('1', 'hostname1', '1',
'hostname2', '1', 'hostname3', '2',
>>> 'hostname10', '2', 'hostname11', '3',
'hostname12');
>>>
>>> I want to turn this list into a hash of
anonymous arrays...something
>>> like this I guess.
>>>
>>> %hash = (
>>> '1' => ['hostname1', 'hostname2',
'hostname3'],
>>> '2' => ['hostname10', 'hostname11'],
>>> '3' => ['hostname12'],
>>> );
>>>
>>>
>>>
>>>
>>> I hope I explained that appropriately.
>>> regards,
>>> J
>>
>> Why don't you post some code showing your attempt
and then we can
>> help you if it doesn't do what you expect? Here's
a hint, to
>> initialize a hash element with an empty array if it
doesn't already
>> have a value, you can do this:
>>
>> $hash{$key} ||= [];
>>
>> I made a subroutine "array_to_hash"
taking a list of values and
>> returning a hash. My little script also used
>> List::MoreUtils::natatime to get the pairs from the
array, but that's
>> not the only way. I also used Data: umper to
produce the output to
>> visually check the result like this:
>>
>>
>> input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3', '2',
>> 'hostname10', '2', 'hostname11', '3',
'hostname12');
>>
>> my %hash = array_to_hash input;
>>
>> print Data: umper-&g
t;Dump([ input, %hash], [qw(*input *hash)]);
>>
>>
>> -Rob
>>
>> Rob Biedenharn http://agileconsultingl
lc.com
>> Rob ...
>>
>
> Rob,
>
> Thanks for the quick response...and your $hash{$key}
||=[] hint
>
> I actually got around this whole thing by retrieving my
data
> differently from DBD::Oracle,
> however I was still intrigued at the problem...I
believe I figured
> it out with your help.
>
> This does what I was looking for, however would there
be a better way?
>
> input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3',
> '2', 'hostname10', '2',
> 'hostname11', '3', 'hostname12');
> my %hash;
>
> my %seen;
You don't need this...
> my $key;
You haven't used this...
But you don't initialize $i (which tells me that you aren't
using the
-w option)
> for ( input; $i <= $#input; $i += 2) {
Should be < not <=, but you get lucky since you're
incrementing by 2
> if (! $seen{$input[$i]}++ ) {
> $hash{$input[$i]} ||= ["$input[$i +
1]"];
Unless you mean to stringify the values, you don't need the
quotes
just like you don't need them in the push.
> } else {
> push {$hash{$input[$i]}}, $input[$i + 1];
> next;
> }
> }
Simplifying and you get (after really using the hint
for (my $i = 0; $i < $#input; $i += 2) {
push {$hash{$input[$i]} ||= []}, $input[$i + 1];
}
> foreach (sort keys %hash) {
> print "$_ --> {$hash{$_}}n";
> }
And for completeness now that you've done your version.
Here's mine:
#!/usr/bin/env perl -w
use List::MoreUtils qw(natatime);
use Data: umper;
sub array_to_hash {
my args = _;
my %hash;
my $iter = natatime 2, args;
while (my ($key, $val) = $iter->()) {
$hash{$key} ||= [];
push {$hash{$key}}, $val;
}
return %hash;
}
input = ('1', 'hostname1', '1', 'hostname2', '1',
'hostname3', '2',
'hostname10', '2', 'hostname11', '3',
'hostname12');
my %hash = array_to_hash input;
print Data: umper-&g
t;Dump([ input, %hash], [qw(*input *hash)]);
__END__
I could have (should have) made the loop body be the single
line:
push {$hash{$key} ||= []}, $val;
I hope that make sense. The Data: umper
library is quite handy to
do quick views of data structures when they grow beyond
simple arrays
and hashes. You might want to check out List::MoreUtils
(and
List::Util) for a number of useful manipulations of lists
(aka, arrays).
-Rob
Rob Biedenharn http://agileconsultingl
lc.com
Rob AgileConsultingLLC.com
Unsubscribing info is here: h
ttp://help.yahoo.com/help/us/groups/groups-32.html
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://g
roups.yahoo.com/group/perl-beginner/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http
://groups.yahoo.com/group/perl-beginner/join
(Yahoo! ID required)
<*> To change settings via email:
mailto:perl-beginner-digest@yahoogroups.com
mailto:perl-beginner-fullfeatured@yahoogroups.com
<*> To unsubscribe from this group, send an email to:
perl-beginner-unsubscribe@yahoogroups.com
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.c
om/info/terms/
|
|
[1-2]
|
|