ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
}
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.
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?
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?
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.
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.
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 aday 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.
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.