how do I create a hash from the list

Discussion in 'Perl Misc' started by Nene, Aug 19, 2011.

  1. Nene

    Nene Guest

    I just used regular expressions to parse out an IP and port. Now how
    do I create a hash from the list.

    Here is the regex I used:
    perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    uniq

    The output of that command is:
    10.10.24.131 7002
    10.10.24.142 7504
    10.10.24.144 7506
    10.10.24.150 7512
    10.10.24.151 7413
    10.10.24.151 7513
    10.10.24.151 7613
    Nene, Aug 19, 2011
    #1
    1. Advertising

  2. Nene <> writes:
    > I just used regular expressions to parse out an IP and port. Now how
    > do I create a hash from the list.
    >
    > Here is the regex I used:
    > perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    > uniq


    '$hash{$1} = $2 if ...' ?
    Rainer Weikusat, Aug 19, 2011
    #2
    1. Advertising

  3. Nene <> wrote:
    >I just used regular expressions to parse out an IP and port. Now how
    >do I create a hash from the list.


    There are many different ways to create many different hashes. What is
    the desired structure/content of that hash (you forgot to tell us....)?

    jue
    Jürgen Exner, Aug 20, 2011
    #3
  4. Nene <> writes:

    > I just used regular expressions to parse out an IP and port. Now how
    > do I create a hash from the list.
    >
    > Here is the regex I used:
    > perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |


    Looks like there might be a missing / in there. See below...

    > uniq


    While you say more about the hash you want to create, here's a tip: you
    don't have to use // for regular expressions. If you precede the
    expression with 'm' you can use something that is more convenient

    if /http:\/\/(\S+):(\d+)\//

    becomes

    if m!http://(\S ):(\d )/!

    or even

    if m{ http:// (\S+) : (\d+) / }x

    (the trailing x lets you add space).

    <snip>
    --
    Ben.
    Ben Bacarisse, Aug 20, 2011
    #4
  5. Nene

    Guest

    On Fri, 19 Aug 2011 14:11:30 -0700 (PDT), Nene <> wrote:

    >I just used regular expressions to parse out an IP and port. Now how
    >do I create a hash from the list.
    >
    >Here is the regex I used:
    >perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    >uniq
    >
    >The output of that command is:
    >10.10.24.131 7002
    >10.10.24.142 7504
    >10.10.24.144 7506
    >10.10.24.150 7512
    >10.10.24.151 7413
    >10.10.24.151 7513
    >10.10.24.151 7613


    You could create an array for the ports.

    -sln

    -----------------------
    use strict;
    use warnings;

    my @data = (
    '10.10.24.131 7002',
    '10.10.24.142 7504',
    '10.10.24.144 7506',
    '10.10.24.150 7512',
    '10.10.24.151 7413',
    '10.10.24.151 7513',
    '10.10.24.151 7613',
    );

    my %gameservers;

    for (sort @data)
    {
    if (/^(\S+)\s+(\d*)$/) {
    push @{$gameservers{$1}}, $2;
    }
    }

    for my $addr (sort keys %gameservers)
    {
    print "adress: $addr ports: ";
    for my $port (sort @{$gameservers{$addr}}) {
    print "$port, ";
    }
    print "\n";
    }

    -------------------
    Output:

    adress: 10.10.24.131 ports: 7002,
    adress: 10.10.24.142 ports: 7504,
    adress: 10.10.24.144 ports: 7506,
    adress: 10.10.24.150 ports: 7512,
    adress: 10.10.24.151 ports: 7413, 7513, 7613,
    , Aug 20, 2011
    #5
  6. Nene

    ccc31807 Guest

    On Aug 19, 5:11 pm, Nene <> wrote:
    > I just used regular expressions to parse out an IP and port. Now how
    > do I create a hash from the list.
    >
    > Here is the regex I used:
    > perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    > uniq
    >
    > The output of that command is:
    > 10.10.24.131 7002
    > 10.10.24.142 7504
    > 10.10.24.144 7506
    > 10.10.24.150 7512
    > 10.10.24.151 7413
    > 10.10.24.151 7513
    > 10.10.24.151 7613


    Perl flattens lists, and a hash is just a flattened list with
    alternating values. For example:

    my %colors = ("A","Apple","B","Bannana","C","Cumquat","D","Date");

    Alternatively:

    my %colors = (A => "Apple, B => "Bannana", C => "Cumquat", D =>
    "Date");

    The => operator is just a shorthand for a comma and quote in a list.

    CC.
    ccc31807, Aug 22, 2011
    #6
  7. Nene

    Ted Zlatanov Guest

    On Fri, 19 Aug 2011 22:22:49 +0100 Rainer Weikusat <> wrote:

    RW> Nene <> writes:
    >> I just used regular expressions to parse out an IP and port. Now how
    >> do I create a hash from the list.
    >>
    >> Here is the regex I used:
    >> perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    >> uniq


    RW> '$hash{$1} = $2 if ...' ?

    It's very unlikely the OP will want to do what you suggest, since he
    shows two clearly identical IPs with different ports:

    10.10.24.131 7002
    10.10.24.142 7504
    10.10.24.144 7506
    10.10.24.150 7512
    10.10.24.151 7413
    10.10.24.151 7513
    10.10.24.151 7613

    Your way would lose the first two ports for 10.10.24.151.

    I typically do this two ways, either

    push @{$hash{$1}}, $2 if ... # keep an array of all the ports in order seen

    or

    $hash{$1}->{$2}++ # keep a hash of all the ports with a count of each

    Of course the OP may need something else--it's not clear what, but I
    would guess it's some variation of the two storage methods above.

    Ted
    Ted Zlatanov, Aug 22, 2011
    #7
  8. Nene

    James Guest

    On Aug 22, 11:04 am, Ted Zlatanov <> wrote:
    > On Fri, 19 Aug 2011 22:22:49 +0100 Rainer Weikusat <> wrote:
    >
    > RW> Nene <> writes:
    > >> I just used regular expressions to parse out an IP and port. Now how
    > >> do I create a hash from the list.

    >
    > >> Here is the regex I used:
    > >> perl -ne 'print "$1 $2\n" if /http:\/\/(\S+):(\d+)\/' {} \; | sort |
    > >> uniq

    >
    > RW> '$hash{$1} = $2 if ...' ?
    >
    > It's very unlikely the OP will want to do what you suggest, since he
    > shows two clearly identical IPs with different ports:
    >
    > 10.10.24.131 7002
    > 10.10.24.142 7504
    > 10.10.24.144 7506
    > 10.10.24.150 7512
    > 10.10.24.151 7413
    > 10.10.24.151 7513
    > 10.10.24.151 7613
    >
    > Your way would lose the first two ports for 10.10.24.151.
    >
    > I typically do this two ways, either
    >
    > push @{$hash{$1}}, $2 if ... # keep an array of all the ports in order seen
    >
    > or
    >
    > $hash{$1}->{$2}++ # keep a hash of all the ports with a count of each
    >
    > Of course the OP may need something else--it's not clear what, but I
    > would guess it's some variation of the two storage methods above.
    >
    > Ted


    Generally speaking,

    @a = qw/aa 1 bb 2 cc 3 dd 4/;
    @b = map {$_%2?"":$_} 0..$#a;
    %h = map {$a[$_] => $a[$_+1]} @b;
    print "$_=>$h{$_}\n" for sort keys %h;

    You get,
    aa=>1
    bb=>2
    cc=>3
    dd=>4

    JL
    James, Aug 25, 2011
    #8
  9. Nene

    Uri Guttman Guest

    >>>>> "J" == James <> writes:

    J> Generally speaking,

    J> @a = qw/aa 1 bb 2 cc 3 dd 4/;

    and this does the same thing as your 3 lines. i am not sure what your
    point is here.

    %h = qw/aa 1 bb 2 cc 3 dd 4/;

    J> @b = map {$_%2?"":$_} 0..$#a;

    that doesn't do what you seem to think it does. print it with
    Data::Dumper.

    J> %h = map {$a[$_] => $a[$_+1]} @b;

    if you had warnings enabled it would tell you something is wrong there.

    J> print "$_=>$h{$_}\n" for sort keys %h;

    have you ever heard of horizontal whitespace? it helps.

    uri

    --
    Uri Guttman -- uri AT perlhunter DOT com --- http://www.perlhunter.com --
    ------------ Perl Developer Recruiting and Placement Services -------------
    ----- Perl Code Review, Architecture, Development, Training, Support -------
    Uri Guttman, Aug 25, 2011
    #9
  10. Nene

    Ted Zlatanov Guest

    On Thu, 25 Aug 2011 14:23:05 -0700 (PDT) James <> wrote:

    J> Generally speaking,

    J> @a = qw/aa 1 bb 2 cc 3 dd 4/;
    J> @b = map {$_%2?"":$_} 0..$#a;
    J> %h = map {$a[$_] => $a[$_+1]} @b;
    J> print "$_=>$h{$_}\n" for sort keys %h;

    J> You get,
    J> aa=>1
    J> bb=>2
    J> cc=>3
    J> dd=>4

    That's not general, readable, or correct. As Uri said you can simply
    assign the first qw// you gave to a hash and it Just Works. But consider

    %a = qw/aa 1 bb 2 cc 3 dd 4 aa 5/;

    Is the 'aa' key 1 or 5? Your approach has the same flaw, it will wipe
    the 'aa' key.

    My suggestion, which you perhaps quoted without understanding it
    completely, ends up with

    # preserve all elements in order
    %a = ( aa => [ 1, 5 ], bb => [ 2 ], cc => [ 3 ], dd => [ 4 ] );

    or with

    # preserve element frequencies (they are all 1 here)
    %a = ( aa => { 1 => 1, 5 => 1 }, bb => ( 2 => 1 ), cc => ( 3 => 1 ), dd => ( 4 => 1 ) );

    which are both useful depending on the need. Also see Hash::Merge on
    CPAN for a general solution to this well-known data structure problem.

    Ted
    Ted Zlatanov, Aug 26, 2011
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    512
    red floyd
    Nov 10, 2011
  2. Anthony Martinez
    Replies:
    4
    Views:
    268
    Robert Klemme
    Jun 11, 2007
  3. Michal Suchanek
    Replies:
    6
    Views:
    226
    Nobuyoshi Nakada
    Jun 13, 2007
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    610
    David A. Black
    Jul 2, 2008
  5. Lynn
    Replies:
    5
    Views:
    142
    Anno Siegel
    Sep 12, 2005
Loading...

Share This Page