Home > Archive > PERL Miscellaneous > July 2005 > multidimensional insertion order
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
multidimensional insertion order
|
|
|
| Is there a way to maintain insertion order in multidimensional hashes
across ALL levels of the hash? If I use Tie::IxHash, it only maintains
the insertion order of the first level. I am parsing a file line by line
and trying to create basically a crosstab html table by converting the
parsed lines to a structured 4-tier hash.
TIA
Caleb
| |
| Abigail 2005-07-27, 10:01 pm |
| Spin (cNaOlSePbA@MvPeLtEsAtSaEr.com) wrote on MMMMCCCXLVIII September
MCMXCIII in <URL:news:11eg3i4rpiq2gd9@corp.supernews.com>:
;; Is there a way to maintain insertion order in multidimensional hashes
;; across ALL levels of the hash? If I use Tie::IxHash, it only maintains
;; the insertion order of the first level. I am parsing a file line by line
;; and trying to create basically a crosstab html table by converting the
;; parsed lines to a structured 4-tier hash.
Use Tie::IxHash on the lower levels as well.
Abigail
--
perl -weprint\<\<EOT\; -eJust -eanother -ePerl -eHacker -eEOT
| |
|
| Abigail wrote:
>
> Use Tie::IxHash on the lower levels as well.
>
>
>
> Abigail
I tried that but I don't know what the keys of the lower levels of the
hash will be. When I put it in just before the loop that builds the
hash, it gave me an error about TIESCALAR.
Caleb
| |
| Paul Lalli 2005-07-28, 5:01 pm |
| Spin wrote:
> Abigail wrote:
>
> I tried that but I don't know what the keys of the lower levels of the
> hash will be. When I put it in just before the loop that builds the
> hash, it gave me an error about TIESCALAR.
Oh, you got "an error"! Well then, you clearly have a problem on line
87 of the 3rd subroutine in your file.
Do you seriously not think the text of the error message might be an
important clue as to what went wrong?
Paul Lalli
| |
| it_says_BALLS_on_your forehead 2005-07-28, 5:01 pm |
| a "hacky" way to do it would be to initialize a counter to 1, and
prepend the counter and an underscore to your key.
then you could sort key on the hash. if the actual key itself is
important (i.e. you need this to be retained) you can take it out
afterwards, using regexs, substr, etc...depending on if you have a
fixed width counter (e.g. 0001, 0002), or not. regex would be s/\d+_//;
hope that helps!
| |
|
| Paul Lalli wrote:
> Oh, you got "an error"! Well then, you clearly have a problem on line
> 87 of the 3rd subroutine in your file.
>
> Do you seriously not think the text of the error message might be an
> important clue as to what went wrong?
>
> Paul Lalli
>
I know 10 programming languages now, which is not a big deal. Except
that of them all Perl has the worst documentation and the most sarcastic
and unhelpful people in its usegroup. Do you not seriously think that I
would rather figure it out myself??? Of course I would! But after 6
hours I thought it might be more effective to stoop and ask for help
after googling the internet.
Rgds,
Caleb
| |
|
| it_says_BALLS_on_your forehead wrote:
> a "hacky" way to do it would be to initialize a counter to 1, and
> prepend the counter and an underscore to your key.
>
> then you could sort key on the hash. if the actual key itself is
> important (i.e. you need this to be retained) you can take it out
> afterwards, using regexs, substr, etc...depending on if you have a
> fixed width counter (e.g. 0001, 0002), or not. regex would be s/\d+_//;
>
> hope that helps!
>
Thanks, I might try that.
Caleb
| |
| Paul Lalli 2005-07-28, 5:01 pm |
| Spin wrote:
> Paul Lalli wrote:
>
> I know 10 programming languages now, which is not a big deal. Except
> that of them all Perl has the worst documentation
False.
> and the most sarcastic
> and unhelpful people in its usegroup.
Well, insulting them is definately the right way to get help out of
them.
> Do you not seriously think that I
> would rather figure it out myself??? Of course I would! But after 6
> hours I thought it might be more effective to stoop and ask for help
> after googling the internet.
Uhhuh... and your point is? *My* point was that in order to get any
kind of decent help, the people you're asking would need to know WHAT
the error message was.
Have you read the Posting Guidelines for this group yet?
Fare thee well
Paul Lalli
| |
| xhoster@gmail.com 2005-07-28, 5:01 pm |
| Spin <cNaOlSePbA@MvPeLtEsAtSaEr.com> wrote:
> Paul Lalli wrote:
>
> I know 10 programming languages now, which is not a big deal. Except
> that of them all Perl has the worst documentation
What are the other 9 languages with better documentation?
> and the most sarcastic
> and unhelpful people in its usegroup.
The sarcasm of people in this group is directly proportional to the moronic
behavior of the OP. If you want less sarcasm, be less of a moron.
> Do you not seriously think that I
> would rather figure it out myself???
We can make that judgement based only on the information you have provided.
Based on that information, it doesn't seem like you are interested in
either figuring it out for yourself, or in having us help you figure it
out. You appear to only be interested in being a cry baby.
> Of course I would! But after 6
> hours I thought it might be more effective to stoop and ask for help
> after googling the internet.
And did you really think that, in asking for help, you should provide us
with absolutely no information to help us help you? And even after this
was pointed out to you, you still fail to provide that information.
Apparently pissing and moaning is far more important than actually getting
help.
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
| |
|
| Alright, let's try again.
I'm parsing a quasi-xml file into a hash, and here is the code that is
relevant:
# keep hashes in order of entry
tie %xml_lines, "Tie::IxHash";
# Open XML file
open (XML, "/samples/radiology2") || die("Can't open XML File: $!.");
$section_number = 1;
# Read XML file into a hash
while (<XML> ) {
trim($_);
if (/^<(.+?)>(.+?)<\/\1>$/) {
$contents = trim($2);
$contents =~ s/\|/<br>/g;
$contents =~ s/<br> /<br>/g;
$contents =~ s/ <br>/<br>/g;
tie $xml_lines{$section}->{$section_number}, "Tie::IxHash";
$xml_lines{$section}->{$section_number}->{$code_name} = $contents;
}
etc
The first tie (tie %xml_lines, "Tie::IxHash";) maintains insertion order
at the {$section_number} level.
The second tie (in the if statement) is where I get the error "Can't
locate object method "TIESCALAR" via package "Tie::IxHash" at
wis_xml_to_html.pl line 56, <XML> line 2."
How do I use Tie::IxHash to maintain the order of insertion in my while
loop at the {$code_name} level?
Apologies to the offended,
Caleb
| |
| Paul Lalli 2005-07-28, 5:01 pm |
| Spin wrote:
> tie $xml_lines{$section}->{$section_number}, "Tie::IxHash";
> The second tie (in the if statement) is where I get the error "Can't
> locate object method "TIESCALAR" via package "Tie::IxHash" at
> wis_xml_to_html.pl line 56, <XML> line 2."
You're attempting to tie a reference to a hash to the Tie::IxHash
class. A reference is a scalar. Therefore, tie() is attempting to use
a non-existant TIESCALAR method.
You *want* to tie the hash that that reference references to the
Tie::IxHash class.
Try: (untested)
tie %{$xml_lines{$section}->{$section_number}}, "Tie::IxHash";
I do not have access to the Tie::IxHash class at the moment, so I can't
test the above. But it makes logical sense to me.
> Apologies to the offended,
Accepted.
Paul Lalli
| |
| Abigail 2005-07-28, 5:01 pm |
| Spin (cNaOlSePbA@MvPeLtEsAtSaEr.com) wrote on MMMMCCCXLIX September
MCMXCIII in <URL:news:11eidvi5qg0tib6@corp.supernews.com>:
--
-- The second tie (in the if statement) is where I get the error "Can't
-- locate object method "TIESCALAR" via package "Tie::IxHash" at
-- wis_xml_to_html.pl line 56, <XML> line 2."
That's because you're trying to tie a scalar. In that case, the tie
mechanism will try to locate the sub TIESCALAR. But you don't want to
tie a scalar, you want to tie a hash. You'll have to do something
like
tie %{$xml_lines{$section}->{$section_number}}, "Tie::IxHash";
Abigail
--
my $qr = qr/^.+?(;).+?\1|;Just another Perl Hacker;|;.+$/;
$qr =~ s/$qr//g;
print $qr, "\n";
| |
|
| Paul Lalli wrote:
> You're attempting to tie a reference to a hash to the Tie::IxHash
> class. A reference is a scalar. Therefore, tie() is attempting to use
> a non-existant TIESCALAR method.
>
> You *want* to tie the hash that that reference references to the
> Tie::IxHash class.
>
> Try: (untested)
>
> tie %{$xml_lines{$section}->{$section_number}}, "Tie::IxHash";
>
>
That truncates the hash somehow.
Using Data::Dumper this is the output from what you suggested above:
%xml_lines = (
'Header' => {
'1' => {
'DOB' => '05/05/02'
}
},
'Gross Necropsy' => {
'1' => {
'Clinician' => 'Joe
Nobody, DVM',
'Report' => 'blah blah blah',
'Report_unparsed' =>
'blah blah blah'
}
},
'Histopathology' => {
'1' => {
'Clinician' => 'Joe
Nobody, DVM',
'Report' => 'blah blah blah',
'Report_unparsed' =>
'blah blah blah'
}
OTOH if I comment the aggravating line out, Data Dumper shows:
%xml_lines = (
'Header' => {
'1' => {
'Sex' => 'Spayed Female',
'Date' => '07/28/05',
'Owner' => 'Joe Somebody',
'Breed' => 'Hedgehog',
'Species' => 'Insectivora',
'DOB' => '05/05/02',
'Patient' => 'Spikey*'
}
},
'Gross Necropsy' => {
'1' => {
'Sex' => 'Spayed Female',
'Template' => 'necropsy',
'Date' => '06/30/05',
'Clinician' => 'Joe
Nobody, DVM',
'Owner' => 'Joe Somebody',
'Breed' => 'Hedgehog',
'Report_unparsed' =>
'blah blah blah',
'Species' => 'Insectivora',
'DOB' => '05/05/02',
'Report' => 'blah blah blah',
'Patient' => 'Spikey*'
}
},
'Histopathology' => {
'1' => {
'Sex' => 'Spayed Female',
'Template' => 'necropsy',
'Date' => '07/11/05',
'Clinician' => 'Joe
Nobody, DVM',
'Owner' => 'Joe Somebody',
'Breed' => 'Hedgehog',
'Report_unparsed' =>
'blah blah blah',
'Species' => 'Insectivora',
'DOB' => '05/05/02',
'Report' => 'blah blah blah',
'Patient' => 'Spikey*'
}
}
);
I changed the output to maintain patient confidentiality; hopefully I
didn't add any typos.
The $section_number is used for occasions when we have >1 report by the
same name. For example, two surgery reports if the patient required two
surgeries while hospitalized. You would understand how essential it is
to have it kept in order at the Section_Number level.
TIA
Caleb
| |
| Tad McClellan 2005-07-28, 5:02 pm |
| Spin <cNaOlSePbA@MvPeLtEsAtSaEr.com> wrote:
> I know 10 programming languages
> Perl has the worst documentation and the most sarcastic
> and unhelpful people in its usegroup.
Then you should consider using any of the 9 "better" languages rather
than Perl.
Good luck!
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Fabian Pilkowski 2005-07-28, 5:02 pm |
| * Spin schrieb:
>
> Alright, let's try again.
> I'm parsing a quasi-xml file into a hash, and here is the code that is
> relevant:
[...]
> tie $xml_lines{$section}->{$section_number}, "Tie::IxHash";
Your $xml_lines{$section}->{$section_number} is just a reference to the
hash. You know about this due to your next line of code:
> $xml_lines{$section}->{$section_number}->{$code_name} = $contents;
You're using Perl's dereferencing operator "->" to access a value of
that reference.
>
> The second tie (in the if statement) is where I get the error "Can't
> locate object method "TIESCALAR" via package "Tie::IxHash" at
> wis_xml_to_html.pl line 56, <XML> line 2."
>
> How do I use Tie::IxHash to maintain the order of insertion in my while
> loop at the {$code_name} level?
Since you don't want to tie a reference [1], you have to tie a hash
instead. Try to dereference the whole hash with "%{}" first:
tie %{ $xml_lines{$section}->{$section_number} }, "Tie::IxHash";
regards,
fabian
[1] A reference is actually stored in a scalar. Thus you get an error
message about "TIESCALAR" (you're trying to tie a scalar and Tie::IxHash
can't do that because it has no mothod named "TIESCALAR"). That's all.
| |
|
| Fabian Pilkowski wrote:
> Since you don't want to tie a reference [1], you have to tie a hash
> instead. Try to dereference the whole hash with "%{}" first:
>
> tie %{ $xml_lines{$section}->{$section_number} }, "Tie::IxHash";
Fabian, that's what I wondered so I tried that (see my previous post)
but that chops off parts of my hash.
Caleb
| |
| xhoster@gmail.com 2005-07-28, 5:02 pm |
| Spin <cNaOlSePbA@MvPeLtEsAtSaEr.com> wrote:
> Paul Lalli wrote:
> That truncates the hash somehow.
When you tie a hash to Tie::IxHash, it empties the hash (which makes sense,
as what else is it going to do with pre-existing, and hence generally
unordered, data?).
You are retying the hash each time through the loop, and so re-emptying it
each time and are left only with the last thing inserted. You want to
detect whether the subhash already exists and then create and tie it only
if and only if it doesn't already exist.
unless ($xml_lines{$section}->{$section_number}) {
tie %{$xml_lines{$section}->{$section_number}}, "Tie::IxHash";
};
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
| |
| xhoster@gmail.com 2005-07-28, 5:02 pm |
| Spin <cNaOlSePbA@MvPeLtEsAtSaEr.com> wrote:
> Paul Lalli wrote:
> That truncates the hash somehow.
When you tie a hash to Tie::IxHash, it empties the hash (which makes sense,
as what else is it going to do with pre-existing, and hence generally
unordered, data?).
You are retying the hash each time through the loop, and so re-emptying it
each time and are left only with the last thing inserted. You want to
detect whether the subhash already exists and then create and tie it only
if it doesn't already exist.
unless ($xml_lines{$section}->{$section_number}) {
tie %{$xml_lines{$section}->{$section_number}}, "Tie::IxHash";
};
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
| |
| Fabian Pilkowski 2005-07-28, 5:02 pm |
| * Spin schrieb:
> Fabian Pilkowski wrote:
>
> Fabian, that's what I wondered so I tried that (see my previous post)
> but that chops off parts of my hash.
Right, I see it know. Last time I connected to my newsserver that
posting wasn't present.
This problem depends on your input data. You hadn't give us any example
thus we give you a first approach to what you want. Now, I assume you're
"re-tieing" your hash. By tieing a already tied hash, this hash will be
discharged. Could this be? Try to prevent this by using Perl's tied()
function to check whether your hash is already tied:
unless ( tied %{...} ) {
tie %{...}, 'Tie::IxHash';
}
or the one-line-version for that:
tie %{...}, 'Tie::IxHash' unless tied %{...};
regards,
fabian
| |
|
| Fabian Pilkowski wrote:
> tie %{...}, 'Tie::IxHash' unless tied %{...};
>
> regards,
> fabian
Bingo! I didn't comprehend that the tieing was doing that.
I appreciate your polite help,
Regards,
Caleb
|
|
|
|
|