FAQ
Hi everyone,

I am new to Perl and I am having some trouble working with hashes of hashes.

I am trying to write a simple Markov Chain text generator and thought
it might be a good idea to keep track of state transitions in a hash.

Here is some of the code I have..

====================================
use Data::Dumper;

my %StateTable = ();

sub InsertWord
{
my( $state, $next ) = shift @_;
if( $StateTable{$state} )
{
if( $StateTable{$state}{$next} )
{
$StateTable{$state}{$next}++;
}else{
$StateTable{$state} = { $next => 1 };
}
}else{
$StateTable{$state} = { $next => 1 };
}
}

InsertWord( "Hello", "World" );
InsertWord( "Hello", "There" );

print Dumper(\%StateTable);
====================================

Currently this does not work as intended. When I dump the hash all I
get is this:

$VAR1 = {
'Hello' => {
'' => 2
}
};

What I want is this:

$VAR1 = {
'Hello' => {
'World' => 1
'There' => 1
}
};

I am looking forward to hearing all your comments.

Thanks,
Greg

Search Discussions

  • Shawn H Corey at Jun 16, 2010 at 10:20 pm

    On 10-06-16 06:02 PM, Greg J wrote:
    Hi everyone,

    I am new to Perl and I am having some trouble working with hashes of hashes.

    I am trying to write a simple Markov Chain text generator and thought
    it might be a good idea to keep track of state transitions in a hash.

    Here is some of the code I have..
    Always put these at the beginning of your scripts:

    use strict;
    use warnings;
    What I want is this:

    $VAR1 = {
    'Hello' => {
    'World' => 1
    'There' => 1
    }
    };

    I am looking forward to hearing all your comments.
    #!/usr/bin/perl

    use strict;
    use warnings;

    use Data::Dumper;

    # Make Data::Dumper pretty
    $Data::Dumper::Sortkeys = 1;
    $Data::Dumper::Indent = 1;

    # Set maximum depth for Data::Dumper, zero means unlimited
    local $Data::Dumper::Maxdepth = 0;

    my %StateTable = ();

    sub InsertWord
    {
    my( $state, $next ) = @_;
    $StateTable{$state}{$next}++;
    }

    InsertWord( "Hello", "World" );
    InsertWord( "Hello", "There" );

    print Dumper(\%StateTable);

    __END__


    --
    Just my 0.00000002 million dollars worth,
    Shawn

    Programming is as much about organization and communication
    as it is about coding.

    The secret to great software: Fail early & often.

    Eliminate software piracy: use only FLOSS.
  • Chas. Owens at Jun 16, 2010 at 10:22 pm
    On Wed, Jun 16, 2010 at 18:02, Greg J wrote:
    snip
    sub InsertWord
    {
    my( $state, $next ) = shift @_;
    snip

    This is your big problem. You need to say

    my ($state, $next) = @_;

    or

    my $state = shift;
    my $next = shift;

    snip
    if( $StateTable{$state} )
    {
    if( $StateTable{$state}{$next} )
    {
    $StateTable{$state}{$next}++;
    }else{
    $StateTable{$state} = { $next => 1 };
    }
    }else{
    $StateTable{$state} = { $next => 1 };
    }
    }
    snip

    You don't need to create anonymous hashes, Perl autovivifies them for
    you. Just say

    $StateTable{$state}{$next}++;

    and Perl will do the right thing. Global variables (%StateTable) are
    evil. Try using OO to make it nicer:

    #!/usr/bin/perl

    use strict;
    use warnings;

    {
    package StateTable;

    sub new {
    my $class = shift;
    return bless {}, $class;
    }

    sub insert_word {
    my $self = shift;
    my ($state, $next) = @_;

    $self->{$state}{$next}++
    }
    }

    my $state_table = StateTable->new;

    $state_table->insert_word("Hello", "World");
    $state_table->insert_word("Hello", "There");

    use Data::Dumper;
    print Dumper $state_table;



    --
    Chas. Owens
    wonkden.net
    The most important skill a programmer can have is the ability to read.
  • Uri Guttman at Jun 16, 2010 at 10:29 pm
    "GJ" == Greg J writes:
    GJ> Hi everyone,
    GJ> I am new to Perl and I am having some trouble working with hashes of hashes.

    GJ> I am trying to write a simple Markov Chain text generator and thought
    GJ> it might be a good idea to keep track of state transitions in a hash.

    GJ> Here is some of the code I have..

    GJ> ====================================
    GJ> use Data::Dumper;

    GJ> my %StateTable = ();

    GJ> sub InsertWord
    GJ> {
    GJ>   my( $state, $next ) = shift @_;

    that is very wrong. either use shift to get one arg or assign @_ to a
    list to get all of them. you used both styles so $next is never set to
    anything (stays undef).

    GJ>   if( $StateTable{$state} )
    GJ>   {
    GJ>      if( $StateTable{$state}{$next} )
    GJ>      {
    GJ>         $StateTable{$state}{$next}++;
    GJ>      }else{
    GJ>        $StateTable{$state} = { $next => 1 };
    GJ>      }

    you don't need the if/else as ++ will work on an undef entry and set it
    to 1. it won't even trigger a warning as this is a common and useful
    idiom.



    GJ>   }else{
    GJ>     $StateTable{$state} = { $next => 1 };

    and you can also dispense with that if/else. just use ||= which won't
    assign if it already has a true value and refs are always true. this
    should replace all the above code (untested):


    $StateTable{$state} ||= { $next => 0 };
    $StateTable{$state}{$next}++;

    note that i set the value to 0 so the ++ will set it to 1.

    for more on hashes of hashes read perldoc perlreftut, perllol and
    perldsc.

    uri

    --
    Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
  • Chas. Owens at Jun 16, 2010 at 10:46 pm
    On Wed, Jun 16, 2010 at 18:29, Uri Guttman wrote:
    snip
    for more on hashes of hashes read perldoc perlreftut, perllol and
    perldsc.
    snip

    Or the online versions:

    http://perldoc.perl.org/perlreftut.html
    http://perldoc.perl.org/perllol.html
    http://perldoc.perl.org/perldsc.html

    --
    Chas. Owens
    wonkden.net
    The most important skill a programmer can have is the ability to read.
  • Uri Guttman at Jun 16, 2010 at 11:36 pm
    "CO" == Chas Owens writes:
    CO> On Wed, Jun 16, 2010 at 18:29, Uri Guttman wrote:
    CO> snip
    for more on hashes of hashes read perldoc perlreftut, perllol and
    perldsc.
    CO> snip

    CO> Or the online versions:

    CO> http://perldoc.perl.org/perlreftut.html
    CO> http://perldoc.perl.org/perllol.html
    CO> http://perldoc.perl.org/perldsc.html

    as a perl teacher i respect says, use the local docs as they are always
    there (given a proper perl installation). learning the perldoc command
    and browsing is fine on your own box. also it is correct for the version
    of perl you have installed vs locating the right version on the web
    site. and you can grep the local docs which is very useful. this isn't
    saying the web stuff isn't good and for some it is, but the primary doc
    source should be local.

    uri

    --
    Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
  • Steve Bertrand at Jun 16, 2010 at 11:57 pm

    On 2010.06.16 19:36, Uri Guttman wrote:
    "CO" == Chas Owens <chas.owens@gmail.com> writes:
    CO> Or the online versions:
    as a perl teacher i respect says, use the local docs as they are always
    there
    ...point well taken. I will personally follow this method from now on.

    If any poster doesn't initially understand as to wtf perldoc is without
    a clicky-gui-type thing, then they can ask. I completely agree that
    expressing to people to be using perldoc as it was originally intended
    to be used, is the proper approach to take.

    Besides, the local docs are the authoritative source, and having the
    most up-to-date documentation for each module/script that one uses is of
    *extreme* importance (imho)... at least for the pod that I write for my
    own modules ;)

    otoh, I don't blame Chas for trying, but I do like the idea of keeping
    Perl, Perl, until asked for further information.

    I keep forgetting that I'm not the only one who knows what Google is.

    Steve

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedJun 16, '10 at 10:02p
activeJun 16, '10 at 11:57p
posts7
users5
websiteperl.org

People

Translate

site design / logo © 2021 Grokbase