Re: Hash problem
by Corion (Patriarch) on Feb 04, 2006 at 00:00 UTC
|
You are not checking if your match is successfull. Only a successfull match sets $1 (and the other variables).
foreach my $try (@array2) {
$try =~ /^(.*),"(.*)",(.*),(.*),"(.*)"/s
or die "Malformed input data: >>$try<<";
...
};
Also consider putting the code you post into <code>...</code> tags, so it can be downloaded and it renders nicely. | [reply] [d/l] [select] |
|
|
I tried this -- and it didn't die.... Thanks for the tip about <code>
| [reply] |
Re: Hash problem
by duckyd (Hermit) on Feb 04, 2006 at 01:10 UTC
|
sort of a side note, but you can't assign a whole array to one hash element - I.E.
if (!$Tex{$a}){$Tex{$a} = @bex};
Will not work. You probably want to use an anonymous array instead:
if (!$Tex{$a}){$Tex{$a} = [@bex] };
| [reply] [d/l] [select] |
|
|
You're right about needing to use a reference to an array for assigning to a hash element, but that way of doing it can be rather wasteful. What you are doing with $Tex{$a} = [@bex] is copying the contents of @bex in to another array and then assign a reference to that new array to $Tex{$a}.
You can avoid the unneccesary copying by just taking a reference to the original array
if (!$Tex{$a}){
$Tex{$a} = \@bex;
}
Of course, this only works correctly in a loop if the array you are taking a reference to is scoped to the loop. If not, your method is correct.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
\@bex won't work unless you do my @bex in the foreach loop. You mentioned this (in less explicit terms), but I just wanted to be clear. Without the my, all values will be references to the same array. In fact, the OP says he's using [@bex], but the symptoms he's describing are those of \@bex.
| [reply] [d/l] [select] |
|
|
|
|
Thanks -- but this hangs my system up!!!!
| [reply] |
Re: Hash problem
by graff (Chancellor) on Feb 04, 2006 at 07:09 UTC
|
What in *heck* am I doing wrong here
Well, ikegami's reply pretty much covered that: what you did wrong was not show any sample data from @array2; you also did not give any clue about what is in @bex.
When you say "the only thing in the hash ... is the last thing added. Everything else has disappeared." um, what is "everything else"? Could it be related to the fact that @bex is never being changed within the foreach loop? I'm wondering why you assign the same array to every hash element.
I'm also wondering why you bother to use capturing parens around 5 strings in the regex, but you only assign four of these to variables, and then you only use one of those variables anywhere else in the loop.
For that matter, I wonder why you're using a greedy regex; maybe "(.*?)" would be better than "(.*)" (but I think split /,/, or maybe Text::xSV or Text::CSV, would be even better than that). | [reply] [d/l] |
Re: Hash problem
by ikegami (Patriarch) on Feb 04, 2006 at 02:10 UTC
|
Maybe if we knoew what was in @array2...
use Data::Dumper;
print(Dumper(\@array2));
| [reply] [d/l] |
Re: Hash problem
by Anonymous Monk on Feb 04, 2006 at 16:45 UTC
|
If I am understanding right you want to create a Hash of arrays with $a as key and (from here I am not quite sure) $b, $c, $d pushed into @bex as the array of $a. Is that right?
Well than please use first use strict; and use warnings; so any problems perl can detect are eliminated.
Then you test if $Tex{$a} is undef in order not to override? But you test just if the value of that key is undefined. Test with exists($Tex{$a}) if you want not to override. Then if you want to add an array although only scalars can be stored into a hash element you will need references. Something like it has beed suggested or: @{$Tex{$a}} = @bex (whatever this @bex is).
Asuming you tested that $a and @bex are ok ...
unless(exists($Tex{$a}))
{
@{$Tex{$a}} = @bex;
}
| [reply] [d/l] |
Re: Hash problem
by ambrus (Abbot) on Feb 04, 2006 at 11:09 UTC
|
| [reply] [d/l] |
Re: Hash problem
by Gnat53 (Novice) on Feb 05, 2006 at 03:06 UTC
|
Dear Monks--
Solved it! Wasn't a hash/array problem at all -- though I'm still not sure why I couldn't print out a list of keys. Anyway, it's working now...
Thank you for all your comments: I know there are better ways of doing things; I'm trying to set the basic thing up first, & then I'll clean it up. What I don't understand is how my code is different from Larry Wall's in PROGRAMMING PERL. Here is his code:
for $group ( "simpsons", "jetsons", "flintstones" ) {
@members = get_family($group);
$HoA{$group} = [ @members ];
}
Do I need to dereference something here to get at it ?
For those who are wondering, @array2 has this kind of data:
"0451524934","1984",7.9500,67,"Penguin Putnam"
"0618056815","42nd Parallel",13.0000,25,"Houghton Mifflin"
"0195167929","A Strange Likeness - Becoming Red and White in Eighteent
+h Century",29.9500,0,"Oxford University Press"
"0520204026","Abortionist : A Woman Against the Law",25.0000,30,"Unive
+rsity of California Press"
Later in my program I push stuff from @array1 onto each array in %Tex. At least in theory. It's weird how many examples, particularly of MySQL, use book information as examples, because that's what I am -- a bookseller.
jdporter added code tags around the data
| [reply] [d/l] [select] |
|
|
"0451524934","1984",7.9500,67,"Penguin Putnam"
"0618056815","42nd Parallel",13.0000,25,"Houghton Mifflin"
"0195167929","A Strange Likeness - Becoming Red and White in Eighteent
+h Century",29.9500,0,"Oxford University Press"
"0520204026","Abortionist : A Woman Against the Law",25.0000,30,"Unive
+rsity of California Press"
(Note that it is possible and preferable to use <code> tags around data samples as well as code snippets.)
Looks like you want to parse each element as CSV data, because it's possible that some of the quoted fields may contain commas, and a simple regex will have trouble with that. Text::CSV will probably be what you want:
use Text::CSV;
# ... load data into @array2
my $csv = Text::CSV->new();
for my $line ( @array2 ) {
if ( $csv->parse( $line )) {
my @fields = $csv->fields;
$Tex{$fields[0]} = \@fields;
# or maybe you want this instead? :
# $Tex{$fields[0]} = [ @fields[1..$#fields] ];
}
else {
warn "CSV parse error on: $line\n";
}
}
(I'm expecting that Text::CSV will remove the quotes that surround some field values, but if it doesn't, you can handle that easily enough.) | [reply] [d/l] [select] |