LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-22-2007, 10:35 AM   #1
the theorist
Member
 
Registered: Apr 2002
Distribution: Fedora Core 5 & 6
Posts: 47

Rep: Reputation: 15
Simple perl problem with hash of arrays


Below is a little perl code with sample input. I'm trying to read the data into a hash of arrays. The left column of the data file is the hash key. Every time a certain hash key is encountered in the input, the right column entry should be added to the appropriate array. At the end, the arrays may be of different length, depending on the input. Here, they are all have two entries for three different hash keys (1,2,3).

When I run this, it looks like the hash isn't getting assigned values, but it does get the keys. The critical push line comes right from the Camel book, so that should work, but apparently doesn't.

Sample data:
Code:
1 2 0
2 3 1
3 4 2

1 2 10
2 3 1
3 4 4
The code:
Code:
#!/usr/bin/perl -w
while(<>){
    next if (m/^\s*$/);
    ($binleft,$binright,$value)=split;   #splits on whitespace by default
    push @{ $datahash{$binleft} } , $value;
    print "$binleft $binright $value\n";   #data looks OK here
}

for $binleft (sort keys %datahash){
    print "datahash: $binleft   $datahash{$binleft}\n";  #try to access through hash, get ARRAY(0x524120), etc.
}
Thanks!
 
Old 07-22-2007, 12:02 PM   #2
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
From page 7 of the second edition or page 10 of the third edition:

Quote:
You can't push or pop a hash though, because it doesn't make sense. A hash has no beginning or end.
Instead of your push statement, what happens when you try this instead?

Code:
$datahash{$binleft}=$value;
Can you give a more extensive, verbatim quote of the Camel book's push example which you quote, and where it is?
 
Old 07-22-2007, 02:55 PM   #3
the theorist
Member
 
Registered: Apr 2002
Distribution: Fedora Core 5 & 6
Posts: 47

Original Poster
Rep: Reputation: 15
Here's what happens...

Quote:
Originally Posted by wjevans_7d1@yahoo.co
Instead of your push statement, what happens when you try this instead?

Code:
$datahash{$binleft}=$value;
Can you give a more extensive, verbatim quote of the Camel book's push example which you quote, and where it is?
Hi! Thanks for the reply!

When I try that simple assignment, I get what I expect: the second data block is written into the hash (overwriting the first data block), and the script prints the second data block.

I don't have my hard copy of the Camel book on me; here is the link at perldoc with the exact same text and extended cartoon character example. I was trying to use the last line of code in the "Generation of a HASH of ARRAYS" block.

I need to have a list of data points associated with each $binleft value. The lists may have different numbers of elements. I need a list context to pass off to a subroutine.

Thanks again!
 
Old 07-22-2007, 05:28 PM   #4
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Um, I have a confession to make.

I am, up to this point, way out of my league here. See, I started with Perl when it was Perl 4. And when I saw all the object-oriented stuff and the extra cruft they put in Perl 5, I said to myself, "Self, if you ever need that stuff, it's time to use C or C++." And that's what I've done.

If I ever needed a hash of arrays, I'd use a hash of strings instead, where each string was created with

Code:
join(",",@array)
... and then I'd use split to split them up again.

But you're right, it can be done with real arrays within real hashes.

Just reading your initial code, without trying anything, it seems that your assignment stuff is ok, but the printing stuff doesn't match anything on the web page to which you refer. (I've put that page in my bookmarks, in case I ever run out of things to do. (grin))

It seems to me you're trying to print the full array within each element of the hash, ja? That would be this, ja?

Code:
 # print the whole thing
 foreach $family ( keys %HoA ) {
     print "$family: @{ $HoA{$family} }\n"
 }
So your code should be:

Code:
for $binleft (sort keys %datahash){
    print "datahash: $binleft  @{ $datahash{$binleft} }\n";
}
This does bring to mind that one of Perl's greatest strengths is also one of its greatest weaknesses: that there are many ways to do a given job in Perl. That makes it easy for the original coder; he only needs to know a limited subset of Perl, that which makes him most comfortable. But anyone else who comes along and maintains Perl code has to know all of Perl, to maintain the favorite idioms of all the original coders he's likely to meet.

That's why, in my opinion, the old simple ways are best. In the long term, simple Perl code is more valuable to your employer, because it's more maintainable by the next guy to come along.

Anyway, does the above snippet fix your situation?
 
Old 07-22-2007, 06:17 PM   #5
the theorist
Member
 
Registered: Apr 2002
Distribution: Fedora Core 5 & 6
Posts: 47

Original Poster
Rep: Reputation: 15
Yes!

ARGH! That was it. So the hash was actually being set up correctly, but my printing statements were wrong! Lesson: evidently the @{} are needed to provide full list context for the hash's arrays. Use them for all printing and other needs, in addition to the initial data read-in.

Thanks very much!

I tried your simple join/split idea, too, but I couldn't get that to work when I wanted to pass one of the hash's strings to a subroutine expecting a list; something like sub( split $datahash{$binleft} ).

Quite a simple stumbling block, but back to work! I mainly program c/c++ as well, but I love perl for these situations where I have lots of data files and just need to do some "simple" reorganization and calculations. I am 'way over my head' too, with perl!

Last edited by the theorist; 07-22-2007 at 06:35 PM.
 
Old 07-23-2007, 07:08 PM   #6
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
IOW, normally (in a simple hash) a hash key 'points' to a scalar value. If it 'points' to an array, you have to tell it by 'casting' the value to an array
Similarly for HoH and so on.
 
Old 07-24-2007, 07:12 AM   #7
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Quoth chrism01:
Quote:
you have to tell it by 'casting' the value
<DROP BODY_PART="Jaw">Sumb*tch.</DROP>So that's what that squirrelly syntax is all about.

I never would have seen it. I feel kinda dumb. Thanks!
 
Old 07-24-2007, 07:28 PM   #8
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
No worries. Technically it's de-referencing an array (or hash) ref, but 'casting' or 'converting' is a more intuitive (?) description.

I tend to think 'cast' because it reminds me of casting types eg float to int in C.
(To other C programmers: i know it's not really the same, its just an aide-memoire when I cvted from C to Perl)

Because it's all done with refs, you can have unlimited structures eg HoHoA.. or AoHoHoA... and so on.
 
Old 07-25-2007, 08:30 PM   #9
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
... which is why, even though I encounter Perl and work with Perl almost every day these days, I detest Perl.

The whole situation rather reminds me of the "one-line programming-language puzzlers" that used to be published in Dr. Dobb's by a debugging-tools company. I kept thinking, "Wow! I wouldn't want to have to be paying some employee his $400 a day to be banging his head writing, much less debugging, any problem at all in a like that! I couldn't afford it!"

And so you can't. (Well, maybe you can, but your boss just threw a chunk of money out the proverbial window. All because of Perl.)

Last edited by sundialsvcs; 07-25-2007 at 08:34 PM.
 
Old 07-26-2007, 01:25 AM   #10
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Seems no worse than C to me. Refs are basically ptrs, so you can build mutilevel structs/records, which is also do-able in C.
It's like casting a ptr in C.
Perl certainly makes handling 'strings' (array-of-char) or any other array type easier for example, because you don't pre-declare their size (or content type) at compile time.
They are dynamically sized and you don't have to worry about going off the end.
Of course, like most langs, you can write unreadable code or you can do it properly. Your choice.
 
  


Reply

Tags
array, hash, perl



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Using hash value as key for other hash in Perl scuzzman Programming 6 02-14-2006 05:08 PM
character arrays; simple problem! drgilberto Programming 2 02-12-2006 04:30 AM
Generating hash in perl ? MikeFoo1 Programming 3 05-21-2005 06:03 PM
Perl: hash tying amnesty_puppy Programming 1 01-17-2005 11:03 PM
Perl XML::Simple - Hash Question smaida Programming 2 05-26-2004 04:20 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:57 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration