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 Code:
#!/usr/bin/perl -w |
From page 7 of the second edition or page 10 of the third edition:
Quote:
Code:
$datahash{$binleft}=$value; |
Here's what happens...
Quote:
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! |
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) 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 Code:
for $binleft (sort keys %datahash){ 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? |
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! |
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. |
Quoth chrism01:
Quote:
I never would have seen it. I feel kinda dumb. Thanks! |
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. |
... 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.) |
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. |
All times are GMT -5. The time now is 06:20 AM. |