in reply to Re: Learning about hashes
in thread Learning about hashes

Thanks for all the suggestions, but I'm still hitting a road block. I don't want to post too much of my code as I am trying to really understand hashes instead of someone just fixing my code.
I think a better question for me now is, how can I pass variables into a hash. Here is a snipit of my code, the variables are defined outside of the while loop.
while <(inFile)> { my @record = split /\|/, $_; my %eslist = $record[3]; }
Ultimately I want to output the unique entries in eslist but I can't even get it to count the number of keys in the hash and I'm getting a "odd number of elements in hash assignment" errors when using use warnings. I'm guessing there is something wrong with how I am trying to pass $record3 into the hash.
When defining the hash I've tried %eslist; and %eslist=(); but I still get the same errors.

Replies are listed 'Best First'.
Re^3: Learning about hashes
by GrandFather (Saint) on Oct 16, 2009 at 05:06 UTC

    A hash stores a key and a value so it doesn't make sense to assign an odd number of elements to a hash. Perhaps your code should look like:

    my %eslist = ($record[3] => 1);

    True laziness is hard work
      Okay, I need help! :) Here is my code so far. What I want to do is send all the unique values in %eslist to a text file. eslist has numbers in it ranging from 1 to 5 digits. I've tried variations on getting eslist into a uniqe file but none of them work so I'm not including them here because I think they are completely wrong and just confusing me. Thanks for any help or direction you can give me.
      use strict; use warnings; my %eslist; open(inFile, "< C:\\input.txt") || die "Unable to open file - $!\n"; open( OUTFILE, "> C:\\output.txt" ) || die "Unable to open write file! - $!\n"; while(<inFile>) { my @record = split /\|/, $_; my $tn = $record[0]; my $err = $record[1]; my $ent = $record[2]; %eslist = ($record[3] => 1); my $coid = $record[4]; } close inFile; close OUTFILE;

        First lets get the general advice out of the way:

        • using strictures (use strict; use warnings;) - very good
        • not using three parameter open - bad
        • not using lexical file handles (see example code below) - bad
        • checking open - very good
        • not providing sample data - vary bad
        • not providing sample output- vary bad
        • providing sample code - excellent

        The following may be what you are looking for. If not, it's at least a good starting point for reframing your question:

        use strict; use warnings; my $sampleData = <<EOF_DATA; 17|5|176|1288|1387 163|1|523|30|6 2592|2|9|1288|6174 152|1|170|1845|473 3|13|50|30|1766 EOF_DATA my %esList; open my $inFile, '<', \$sampleData or die "Unable to open file - $!\n" +; while (defined (my $line = <$inFile>)) { my ($tn, $err, $ent, $es, $coid) = split /\|/, $line; $esList{$es} = $line if ! exists $esList{$es}; } close $inFile; print $esList{$_} for sort {$a <=> $b} keys %esList;

        Prints:

        163|1|523|30|6 17|5|176|1288|1387 152|1|170|1845|473

        True laziness is hard work
Re^3: Learning about hashes
by toolic (Bishop) on Oct 16, 2009 at 01:09 UTC
    my %eslist = $record[3];
    That code declares a hash variable (using my) and assigns a single scalar value to the hash. In the words of diagnostics
    (W) You specified an odd number of elements to initialize a hash, which is odd, because hashes come in key/value pairs.
    What is in $record[3]? What other data do you want to associate with $record[3]? If you show us a small sample of data, we could probably suggest how you might store the data in a hash.

    Give perldata a quick read.

      record[3] is a bunch of numbers. I'm trying to find all unique entries. From what I've read a hash is the best way to do this, but I'm having trouble understanding how to assign a key to the record[3] value. Is a key like a primary key in a database? Where it is essentially a arbitrary unique number used to refer to the entry?
Re^3: Learning about hashes
by DamianKaelGreen (Acolyte) on Oct 22, 2009 at 16:58 UTC
    OK, I think I see what you are trying to do, but a hash may not be what you want. A list might be better for your needs. List ex:
    use List::MoreUtils qw(any); #instead of using: # "if (grep( m/whatever/, @list)){}" #use: "if (any { m/whatever/} @list){}" #this exits on the first occurrence. if (!any {m/^\Q$record[3]\E$} @esList){ #the \Q\E guarantees that the value held in the $record[3] #is not interpreted as a regular expression push (@esList = $record[3]); } ### @esList is now a unique list of the values you want...
    But if you really want to use a hash, this is how you might do it:
    my %esList = (); $esList{$record[3]) = 1; ### then to recall all the found records: foreach my $result {sort(keys(%esList))){ print "found record: $result \n"; }
    Also, if you're interested, I started a discussion recently about how to best implement multidimensional hashes, they have some unique characterictics that you might not expect when trying to extending principals of a one dimensional hash. But there are some very good references listed there. It can be found at: Best Multidimensional Hash Practices? Good luck...