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

I want to convert an array to hash in given format:

@array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8); %hash = ('a' => [1,2,3,4], 'b' => [6,7,8]);

Replies are listed 'Best First'.
Re: Create a hash whose keys and values come from a given array
by GrandFather (Saint) on Sep 06, 2017 at 06:42 UTC

    Why? What is the bigger picture problem you are trying to solve?

    If that is the exact array you want to convert then just use the hash as specified. If the array contains something different then you haven't really given us enough information to help you. What is the rule for distinguishing between keys and values? Very likely it is easier to directly construct the hash from whatever process generates the array and not generate the array at all.

    Premature optimization is the root of all job security
Re: Create a hash whose keys and values come from a given array
by kcott (Archbishop) on Sep 06, 2017 at 06:51 UTC

    G'day IruP,

    Welcome to the Monastery.

    The following achieves what you ask; however, you've not been clear on what exact formats the keys, and values for the arrayrefs, take. So, the following code shows the basic technique; but, when you have a better specification, the specific elements of the code may well need to be changed.

    #!/usr/bin/env perl use strict; use warnings; use Data::Dump; my @array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8); my %hash; my $key; for my $element (@array) { if ($element =~ /^\D$/) { $key = $element; } else { push @{$hash{$key}}, $element; } } dd \%hash;

    Output:

    { a => [1 .. 4], b => [6, 7, 8] }

    See Data::Dump if you're unfamiliar with that module; the builtin Data::Dumper module has similar functionality.

    — Ken

Re: Create a hash whose keys and values come from a given array
by AnomalousMonk (Archbishop) on Sep 06, 2017 at 06:46 UTC

    You seem to want a very arbitrary structure, but here's one way for the given example data:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8); ;; my %hash = ( $array[0] => [ @array[ 1 .. 4 ] ], $array[5] => [ @array[ 6 .. 8 ] ], ); ;; dd \%hash; " { a => [1, 2, 3, 4], b => [6, 7, 8] }
    Can you be more specific about what you really want?


    Give a man a fish:  <%-{-{-{-<

Re: Create a hash whose keys and values come from a given array
by karlgoethebier (Abbot) on Sep 06, 2017 at 11:49 UTC

    A TMTOWTDI for learning purposes and fun:

    #!/usr/bin/env perl # $Id: 1198743.pl,v 1.5 2017/09/06 11:32:17 karl Exp karl $ # http://perlmonks.org/?node_id=1198743 use strict; use warnings; use feature qw(say); use Data::Dump; my @array = ( 'a', 1, 2, 3, 4, 'b', 6, 7, 8 ); my %hash; my @keys = grep { /\D/ } @array; my @values = map { [ split "", $_ ] } split /\D/, join "", @array; shift @values; @hash{@keys} = @values; dd \%hash; __END__ karls-mac-mini:monks karl$ ./1198743.pl { a => [1 .. 4], b => [6, 7, 8] }

    See also grep, map, split and shift.

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Create a hash whose keys and values come from a given array
by clueless newbie (Curate) on Sep 06, 2017 at 09:42 UTC

    Using autobox

    use autobox::universal qw(type); use Data::Dumper; use strict; use warnings; my @array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8); my %hash = (); my $key; for (@array) { if (type($_) eq 'STRING') { $key=$_; } else { push @{$hash{$key}},$_; } } warn Data::Dumper->Dump([\%hash],[qw(*hash)]),' ';

      Nice. But I would just use /\D/ to detect a non-numeric array element. No need to mess with automatically-generated classes:

      # no "use autobox::universal" # ... for (@array) { if (/\D/) { $key=$_; } else { push @{$hash{$key}},$_; } } # ...

      Alternatively, use looks_like_number() from Scalar::Util that wraps the Perl API function of the same name:

      # ... use Scalar::Util qw( looks_like_number ); # ... for (@array) { if (looks_like_number($_)) { $key=$_; } else { push @{$hash{$key}},$_; } } # ...

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
        Autobox and \D play differently:
        use autobox::universal qw(type); use Data::Dumper; use strict; use warnings; my @array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8, '1', 2, 3, 4, 5); # note t +he '1' which autobox will call a string. my %hash = (); my $key; for (@array) { if (type($_) eq 'STRING') { $key=$_; } else { push @{$hash{$key}},$_; } } warn Data::Dumper->Dump([\%hash],[qw(*hash)]),' ';
        The output from Data::Dumper:
        %hash = ( '1' => [ 2, 3, 4, 5 ], 'b' => [ 6, 7, 8 ], 'a' => [ 1, 2, 3, 4 ] );
Re: Create a hash whose keys and values come from a given array
by tybalt89 (Monsignor) on Sep 06, 2017 at 21:27 UTC

    It's almost a one-liner :)

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1198743 use strict; use warnings; use Data::Dump 'pp'; my @array = ('a', 1, 2, 3, 4, 'b', 6, 7, 8); my $ref; my %hash = map { /\D/ ? ($_ => $ref = []) : (push @$ref, $_) x 0 } @ar +ray; pp \%hash;

    Outputs:

    { a => [1 .. 4], b => [6, 7, 8] }
Re: Create a hash whose keys and values come from a given array
by hippo (Archbishop) on Sep 07, 2017 at 13:37 UTC