Idiot Q: How to find index number of HASH match?

F

Franzl Wisseworst

I wonder how to find the reference to the HASH position based on a matching
'page-name'. My page-name is always known in the $current::page

$current::page;

Here are two hash tables, with 3 links each:

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

The script also knows the user is on the 'en' domain in order to search for
a match in %location_en, so knowing this, how could it crawl through the
%location_en hash to return the index number of that array in order to
generate a link to the same position in %location_de, i.e. blau.html?

No doub't many ways exist, while in this case the simplest would be the
best, and without performance limitations (eg. use of RE's). Its simply an
html pre-processing procedure that runs once in a blue moon on a localhost
to generate static pages that are later sent up on a server in plain html.
 
E

Eric Schwartz

Franzl Wisseworst said:
Here are two hash tables, with 3 links each:

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

The script also knows the user is on the 'en' domain in order to search for
a match in %location_en, so knowing this, how could it crawl through the
%location_en hash to return the index number of that array in order to
generate a link to the same position in %location_de, i.e. blau.html?

When you use a hash, the concept of "index number" is completely
meaningless. Hashes are indexed by strings, not numbers. Once you
put a key/value pair into a hash, you have no control over where it
ends up.[0] I think you want a multilevel hash, instead:

%location = ( page1 => { en => { name => "page one",
url => "page1.html" },
de => { name => "Seite eins",
url => "seite1.html" }
},
blah => { en => { name => "blabla",
url => "bla.html" },
de => { name => "Blau",
url => "blau.html" }
}
# .... and so on
);

You can get at any page by saying:

my $url = $location{page1}{en}{url};

Read perlreftut for more on how I created this, if you're not already
familiar with references.

-=Eric

[0] You can use Tie::IxHash, but that's missing the point.
 
E

Eric Amick

I wonder how to find the reference to the HASH position based on a matching
'page-name'. My page-name is always known in the $current::page

$current::page;

Here are two hash tables, with 3 links each:

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

The script also knows the user is on the 'en' domain in order to search for
a match in %location_en, so knowing this, how could it crawl through the
%location_en hash to return the index number of that array in order to
generate a link to the same position in %location_de, i.e. blau.html?

Hashes don't work that way. There's no guarantee the keys will remain in
the order you specified them when you added them to the hash, and
expecting any similar correspondence between two hashes is hopeless. If
you want a translation, one possibility would be to have arrays for hash
values such as this:

%location_en = ('page1.html' =>['page one', 'Seite eins'],
'bla.html' => ['blabla', 'Blau'],
'something.html' => ['Something', 'Ding']);

The English value would be accessed as, for example,
$location_en{'page1.html'}[0], and its German equivalent as
$location_en{'page1.html'}[1].
 
J

Jürgen Exner

Franzl said:
I wonder how to find the reference to the HASH position based on a
matching 'page-name'.

That 'page-name' _is_ the position in the hash. If you are looking for
something like a sequence or a next or previous then use an array instead.
That's what arrays are for.
My page-name is always known in the
$current::page

$current::page;

Here are two hash tables, with 3 links each:

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');


I have been working in software localization for about 8 years.
From experience I can tell you that it is _far_ easier not to localize any
file names. You are asking for unnecessary difficulties if you do

Just put the English files into a subtree 'en' and mirror that subtree using
the German files under a folder 'de'. Makes life a lot easier.

If you want to map file names, then you need another table to do exactly
that:

%map-en-de = ('page1.html' => 'seite1.html',
'bla.html' => 'blau.thml',
.....


jue

jue
 
F

Franzl Wisseworst

Thank you for the various comments above which sheds much light as well as
more confusion on the situation....

The multi-level hash is probably the method I need.
 
F

Franzl Wisseworst

While I'm still pondering about how to best solve the above question by the
various solutions posted in response, I have now a different question,
although ultimately for the one and same purpose.

The below script is a bare-bone version, without the language multi-arrays
attempt. It simply generates groups of unordered html-lists which form the
basis of a navigation system.

The navigation will have a bunch of UL's and LI's glued together in
css drop menu fashion, but I've cut that css out from this post.

Each group of links will have several LI's nested within the first-level UL
and LI entry, like this:

<ul>
<li class=yellow>page one
<ul>
<li>DING</li>
<li>Something</li>
</ul>

The current page is identified through an $ENV{"DOCUMENT_NAME"} call. The
whole thing is generated via SSI and the script resides in a dot-pl file.

In case the current page exists in one of the hash arrays, the resulting
css-class is set to "yellow" and subsequently the background of the
list items contained in its css-block all become yellow. For example, the
background of the first <li> and nested <ul><li>'s will be yellow when the
page DING is viewed.

For user-friendliness sake I'd like the current page (e.g. DING) not to be
a link to itself when it is viewed.

My question is therefore, how would one normally omit the enclosing <a
href=$_> and </a> html-code output based on a particular condition, in this
case if and where the current page name ($current::page) match exists?

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

The complete script is included below:

#!/usr/bin/perl -w

print "Content-type: text/html\n\n";

# bg css-color to visually indicate which group of
# links/ul current page exists in

######## css bits #########

print "<head>\n";
print "<style>\n";
print ".green {background:green;}\n";
print ".yellow {background:yellow;\n";
print "</style>\n";
print "</head>\n\n";


######## some pre-procedures ########

use Tie::IxHash;
use strict;
use warnings;

tie my %location, "Tie::IxHash";
tie my %activities, "Tie::IxHash";

# Place CGI environment variable in
# $current::page global
# needed later to identify if page is in group

if ($ENV{"DOCUMENT_NAME"}){
$current::page = $ENV{"DOCUMENT_NAME"};
}
else {
$current::page = "undefined";
}

print $current::page;


######### the hashes with links ##########


%location = ('page1.html' => 'page one',
'ding.html' => 'DING',
'something.html' => 'Something');

%activities = ('fishing.html' => 'Fishing',
'diving.html' => 'Diving',
'drinking.html', => 'Beer');


##### display first group of links with a loop ####

if (exists($location{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>\n";

for (\%location) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$location{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$location{$_}</a></li> \n" while local $_ = each %$_;
print "</ul>\n";
print "</li>\n";
}
print "</ul>";


#### display second group of links with loop ####

if (exists($activities{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>";

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

print "</ul>";

# etc...

No doubt there exists more compact methods for the whole procedure,
especially when there are many more groups of links. But code-bloat is not
a problem here, as the script simply generate static pages once in a while
which are later sent up on a server via automated ftp procedures. Instead
configurability and exception to rules may be more important in the future.

The purpose of the perl script is simply to remove tedious and error prone
cross page html coding, while still retaining that old tailor made quality.
 
F

Franzl Wisseworst

While I'm still pondering about how to best solve the above question by the
various solutions posted in response, I have now a different question,
although ultimately for the one and same purpose.

The below script is a bare-bone version, without the language multi-arrays
attempt. It simply generates groups of unordered html-lists which form the
basis of a navigation system.

The navigation will have a bunch of UL's and LI's glued together in
css drop menu fashion, but I've cut that css out from this post.

Each group of links will have several LI's nested within the first-level UL
and LI entry, like this:

<ul>
<li class=yellow>page one
<ul>
<li>DING</li>
<li>Something</li>
</ul>
</ul>

The current page is identified through an $ENV{"DOCUMENT_NAME"} call. The
whole thing is generated via SSI and the script resides in a dot-pl file.

In case the current page exists in one of the hash arrays, the resulting
css-class is set to "yellow" and subsequently the background of the
list items contained in its css-block all become yellow. For example, the
background of the first <li> and nested <ul><li>'s will be yellow when the
page DING is viewed.

For user-friendliness sake I'd like the current page (e.g. DING) not to be
a link to itself when it is viewed.

My question is therefore, how would one normally omit the enclosing <a
href=$_> and </a> html-code output based on a particular condition, in this
case if and where the current page name ($current::page) match exists?

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

The complete script is included below:

#!/usr/bin/perl -w

print "Content-type: text/html\n\n";

# bg css-color to visually indicate which group of
# links/ul current page exists in

######## css bits #########

print "<head>\n";
print "<style>\n";
print ".green {background:green;}\n";
print ".yellow {background:yellow;\n";
print "</style>\n";
print "</head>\n\n";


######## some pre-procedures ########

use Tie::IxHash;
use strict;
use warnings;

tie my %location, "Tie::IxHash";
tie my %activities, "Tie::IxHash";

# Place CGI environment variable in
# $current::page global
# needed later to identify if page is in group

if ($ENV{"DOCUMENT_NAME"}){
$current::page = $ENV{"DOCUMENT_NAME"};
}
else {
$current::page = "undefined";
}

print $current::page;


######### the hashes with links ##########


%location = ('page1.html' => 'page one',
'ding.html' => 'DING',
'something.html' => 'Something');

%activities = ('fishing.html' => 'Fishing',
'diving.html' => 'Diving',
'drinking.html', => 'Beer');


##### display first group of links with a loop ####

if (exists($location{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>\n";

for (\%location) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$location{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$location{$_}</a></li> \n" while local $_ = each %$_;
print "</ul>\n";
print "</li>\n";
}
print "</ul>";


#### display second group of links with loop ####

if (exists($activities{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>";

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

print "</ul>";

# etc...

No doubt there exists more compact methods for the whole procedure,
especially when there are many more groups of links. But code-bloat is not
a problem here, as the script simply generate static pages once in a while
which are later sent up on a server via automated ftp procedures. Instead
configurability and exception to rules may be more important in the future.

The purpose of the perl script is simply to remove tedious and error prone
cross page html coding, while still retaining that old tailor made quality.
 
F

Franzl Wisseworst

While I'm still pondering about how to best solve the above question by the
various solutions posted in response, I have now a different question,
although ultimately for the one and same purpose.

The below script is a bare-bone version, without the language multi-arrays
attempt. It simply generates groups of unordered html-lists which form the
basis of a navigation system.

The navigation will have a bunch of UL's and LI's glued together in
css drop menu fashion, but I've cut that css out from this post.

Each group of links will have several LI's nested within the first-level UL
and LI entry, like this:

<ul>
<li class=yellow>page one
<ul>
<li>DING</li>
<li>Something</li>
</ul>
</li>
</ul>

The current page is identified through an $ENV{"DOCUMENT_NAME"} call. The
whole thing is generated via SSI and the script resides in a dot-pl file.

In case the current page exists in one of the hash arrays, the resulting
css-class is set to "yellow" and subsequently the background of the
list items contained in its css-block all become yellow. For example, the
background of the first <li> and nested <ul><li>'s will be yellow when the
page DING is viewed.

For user-friendliness sake I'd like the current page (e.g. DING) not to be
a link to itself when it is viewed.

My question is therefore, how would one normally omit the enclosing <a
href=$_> and </a> html-code output based on a particular condition, in this
case if and where the current page name ($current::page) match exists?

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

The complete script is included below:

#!/usr/bin/perl -w

print "Content-type: text/html\n\n";

# bg css-color to visually indicate which group of
# links/ul current page exists in

######## css bits #########

print "<head>\n";
print "<style>\n";
print ".green {background:green;}\n";
print ".yellow {background:yellow;\n";
print "</style>\n";
print "</head>\n\n";


######## some pre-procedures ########

use Tie::IxHash;
use strict;
use warnings;

tie my %location, "Tie::IxHash";
tie my %activities, "Tie::IxHash";

# Place CGI environment variable in
# $current::page global
# needed later to identify if page is in group

if ($ENV{"DOCUMENT_NAME"}){
$current::page = $ENV{"DOCUMENT_NAME"};
}
else {
$current::page = "undefined";
}

print $current::page;


######### the hashes with links ##########


%location = ('page1.html' => 'page one',
'ding.html' => 'DING',
'something.html' => 'Something');

%activities = ('fishing.html' => 'Fishing',
'diving.html' => 'Diving',
'drinking.html', => 'Beer');


##### display first group of links with a loop ####

if (exists($location{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>\n";

for (\%location) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$location{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$location{$_}</a></li> \n" while local $_ = each %$_;
print "</ul>\n";
print "</li>\n";
}
print "</ul>";


#### display second group of links with loop ####

if (exists($activities{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>";

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;
print "</ul>\n";
print "</li>\n";
}

print "</ul>";

# etc...

No doubt there exists more compact methods for the whole procedure,
especially when there are many more groups of links. But code-bloat is not
a problem here, as the script simply generate static pages once in a while
which are later sent up on a server via automated ftp procedures. Instead
configurability and exception to rules may be more important in the future.

The purpose of the perl script is simply to remove tedious and error prone
cross page html coding, while still retaining that old tailor made quality.
 
F

Franzl Wisseworst

For user-friendliness sake I'd like the current page (e.g. DING) not to be
a link to itself when it is viewed.

I can get the first level UL/LI to display conditionally as in below code.
The first UL ($firstkey) always contains only one LI entry however.

What I can't figure is how to do the same in the while part for the nested
UL/LI's below, if at all possible with the hash as currently set-up?

print "<ul>\n";

for (\%location) {

my $firstkey = each %$_;
if ($current::page eq $firstkey){
print "<li class=$class::value>$location{$firstkey}"; # <-- no-link OK !
}
else {
print "<li class=$class::value><a href=$firstkey>$location{$firstkey}</a>";
}

print "<ul>\n";
print "<li><a href=$_>$location{$_}</a></li> \n"while local $_ = each %$_;
# how on earth can I do the same in the above line?!?

print "</ul>\n";
print "</li>\n";
}
print "</ul>";
 
T

Tad McClellan

Franzl Wisseworst said:
My question is therefore, how would one normally omit the enclosing <a
href=$_> and </a> html-code output based on a particular condition, in this
case if and where the current page name ($current::page) match exists?

for (\%activities) {
my $firstkey = each %$_;
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
print "<ul>\n";
print "<li><a href=$_>$activities{$_}</a></li> \n" while local $_ = each
%$_;


while ( local $_ = each %$_ ) {
if ( exists $activities{$_} )
{ print "<li>$activities{$_}</li> \n" }
else
{ print "<li><a href=$_>$activities{$_}</a></li> \n" }
}

print "</ul>\n";
print "</li>\n";
}
[snip]

if ($ENV{"DOCUMENT_NAME"}){
$current::page = $ENV{"DOCUMENT_NAME"};
}
else {
$current::page = "undefined";
}


You could replace all of that with:

$current::page = $ENV{DOCUMENT_NAME} || 'undefined';
 
F

Franzl Wisseworst

Tad McClellan wrote:

[..]
while ( local $_ = each %$_ ) {
if ( exists $activities{$_} )
{ print "<li>$activities{$_}</li> \n" }
else
{ print "<li><a href=$_>$activities{$_}</a></li> \n" }
}

Thank you for the above code. I'v been staring at it for a while and can't
understand why it shouldn't work.

But for some reason it always opts for the if condition to return the
no-link version no matter what the $current::page is so that all <li>'s in
the nested <ul> block becomes no-links.

Or its just too early in the morning for my cut-and-paste skills to work....

I've copied in the complete code down below, now including an if procedure
for the $firstkey hash occurance of the for loop, which does work to
display the no-link if page1.html is accessed, and otherwise displays the
relevant entry as a link as it should.

Its only the while-if-else bit posted above which I can't get to work for
in my code for some reason. Any ideas?

#!/usr/bin/perl -w

print "Content-type: text/html\n\n";

######## css bits #########

print "<head>\n";
print "<style>\n";
print ".green {background:green;}\n";
print ".yellow {background:yellow;\n";
print "</style>\n";
print "</head>\n\n";

######## some pre-procedures ########

use Tie::IxHash;
use strict;
use warnings;

tie my %location, "Tie::IxHash";
tie my %activities, "Tie::IxHash";

# Thanks for this bit, this much I can understand at this hour
$current::page = $ENV{DOCUMENT_NAME} || 'undefined';

######### the hashes with links ##########

%location = ('page1.html' => 'page one',
'ding.html' => 'DING',
'something.html' => 'Something');

%activities = ('fishing.html' => 'Fishing',
'diving.html' => 'Diving',
'trekking.html', => 'Trekking');

##### display first group of links with a loop ####

if (exists($location{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}

print "<ul>\n";

for (\%location) {

my $firstkey = each %$_;
if ($current::page eq $firstkey){
print "<li class=$class::value>$location{$firstkey}\n";
}
else {
print "<li class=$class::value><a
href=$firstkey>$location{$firstkey}</a>\n";
}


print "<ul>\n";

# previous code:
# print "<li><a href=$_>$location{$_}</a></li> \n"while local $_ = each %$_;

# new code:
while ( local $_ = each %$_ ) {
if ( exists $location{$_} )
{ print "<li>$location{$_}</li> \n" }
else
{ print "<li><a href=$_>$location{$_}</a></li> \n" }
}

print "</ul>\n";
print "</li>\n";
}
print "</ul>";

#### display second group of links with loop ####

if (exists($activities{$current::page})){
$class::value = "yellow";
}

else {
$class::value = "green";
}


print "<ul>";

for (\%activities) {
my $firstkey = each %$_;

if ($current::page eq $firstkey){
print "<li class=$class::value>$activities{$firstkey}\n";
}
else {
print "<li class=$class::value><a
href=$firstkey>$activities{$firstkey}</a>\n";
}

print "<ul>\n";

# previous code:
# print "<li><a href=$_>$activities{$_}</a></li>" while local $_ = each %$_;

# new code:
while ( local $_ = each %$_ ) {
if ( exists $activities{$_} )
{ print "<li>$activities{$_}</li> \n" }
else
{ print "<li><a href=$_>$activities{$_}</a></li> \n" }
}


print "</ul>\n";
print "</li>\n";
}

print "</ul>";
 
F

Franzl Wisseworst

Tad said:
[..]
while ( local $_ = each %$_ ) {
if ( exists $activities{$_} )
{ print "<li>$activities{$_}</li> \n" }
else
{ print "<li><a href=$_>$activities{$_}</a></li> \n" }
}

I managed to modify the above so it outputs what is needed. The above
example were comparing: ...
if ( exists $activities{$_} )
... for some reason it made all entries into no-links.

while if instead I do: ...
if ( $current::page eq $_)

.... it then works! I.e. links are links where they should be links and no
links are no links where there should be no links.

while ( local $_ = each %$_ ) {
if ( $current::page eq $_)
{ print "<li>$activities{$_}</li> \n" }
else
{ print "<li><a href=$_>$activities{$_}</a></li> \n" }
}

Many thanks for your help with the while-if-else construct.
 
F

Franzl Wisseworst

Jürgen Exner said:
file names. You are asking for unnecessary difficulties if you do

I agree on the easy life part. If however one wants a true localisation
where page names should ideally relate to content for some reason, keyword
ranking included, then localised URL's are usually better.

But if your typical url is http://www.mapquest.com/maps/map.adp?ovi=1&mqma
p.x=300&mqmap.y=75&mapdata=%252bKZmeiIh6N%252bI
gpXRP3bylMaN0O4z8OOUkZWYe7NRH6ldDN96YFTIUmSH3Q6
OzE5XVqcuc5zb%252fY5wy1MZwTnT2pu%252bNMjOjsHjvN
lygTRMzqazPStrN%252f1YzA0oWEWLwkHdhVHeG9sG6cMrf
XNJKHY6fML4o6Nb0SeQm75ET9jAjKelrmqBCNta%252bsKC
9n8jslz%252fo188N4g3BvAJYuzx8J8r%252f1fPFWkPYg%
252bT9Su5KoQ9YpNSj%252bmo0h0aEK%252bofj3f6vCP

.... then it makes no difference in terms of user experience.

But umlauts etc., I opt for replacing with English characters.
%map-en-de = ('page1.html' => 'seite1.html',
'bla.html' => 'blau.thml',

Many thanks for the information.
 
F

Franzl Wisseworst

Could anyone point me towards the right methods before I digress in all
directions? I should have done my homework first, but the problem is as
always too little time and too many ways of doing the same thing....

I have 2 separate hashes, the content within is used to construct a
navigation menu. This has already been solved with much help on this group.

I would like to make use of the data within the hashes for language
switching between web pages. Every page always has a mirror in a second
language, in other words, the structure and order always remains identical.

Instead of opting for a more sophisticated multi-dimensional hash array
method as disussed in previous posts of this string, I guess another and
possibly easier solution would be simply to copy the keys into a standard
array, and then use index numbers to identify the mirror pages of the other
language version.

For now I have something as follows:

use Tie::IxHash;

tie my %location_en, "Tie::IxHash";
tie my %location_de, "Tie::IxHash";

$current::page = $ENV{DOCUMENT_NAME} || 'undefined';

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

So to utilise the existing data, as opposed to maintain hashes and arrays
with partly duplicate data, I'd like to:

1) Copy the keys, i.e. the page URL's or filenames from %location_en into
an normal array where I can easier refer to them by index.

Exactly how would "page1.html", "bla.html" and "something.html" be placed
in a standard array named @location_en. A simply question I know...

2) Search the array for a possible match of the filename as already held in
the global $current::page variable and return its index number. In the
unlikely event no match is found, return a fixed string, e.g. "404.html".

4) Extract the string in %location_de that has the same index number as in
%location_de. But I guess this must be a too simple question....

In any case, thank you for any helpful pointers, especially regarding
question #1 and #2.
 
F

Franzl Wisseworst

Could anyone point me towards the right methods before I digress in all
directions? I should have done my homework first, but the problem is as
always too little time and too many ways of doing the same thing....

I have 2 separate hashes, the content within is used to construct a
navigation menu. This has already been solved with much help on this group.

I would like to make use of the data within the hashes for language
switching between web pages. Every page always has a mirror in a second
language, in other words, the structure and order always remains identical.

Instead of opting for a more sophisticated multi-dimensional hash array
method as disussed in previous posts of this string, I guess another and
possibly easier solution would be simply to copy the keys into a standard
array, and then use index numbers to identify the mirror pages of the other
language version.

For now I have something as follows:

use Tie::IxHash;

tie my %location_en, "Tie::IxHash";
tie my %location_de, "Tie::IxHash";

$current::page = $ENV{DOCUMENT_NAME} || 'undefined';

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

So to utilise the existing data, as opposed to maintain hashes and arrays
with partly duplicate data, I'd like to:

1) Copy the keys, i.e. the page URL's or filenames from %location_en into
an normal array where I can easier refer to them by index.

Exactly how would "page1.html", "bla.html" and "something.html" be placed
in a standard array named @location_en. A simply question I know...

2) Search the array for a possible match of the filename as already held in
the global $current::page variable and return its index number. In the
unlikely event no match is found, return a fixed string, e.g. "404.html".

3) Extract the string in %location_de that has the same index number as in
%location_en. But I guess this must be a too simple question....

In any case, thank you for any helpful pointers, especially regarding
question #1 and #2.
 
J

Jürgen Exner

Franzl said:
%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

So to utilise the existing data, as opposed to maintain hashes and
arrays with partly duplicate data, I'd like to:

1) Copy the keys, i.e. the page URL's or filenames from %location_en
into an normal array where I can easier refer to them by index.

@normalarray = keys (%location_en);
Of course the sequence of the keys in @normalarray will be random for all
practical purposes.

If you want a defined sequence then use
@normalarray = ('page1.html', 'bla.html', 'something.html');
Exactly how would "page1.html", "bla.html" and "something.html" be
placed in a standard array named @location_en. A simply question I
know...

@location_en = ('page1.html', 'bla.html', 'something.html');
2) Search the array for a possible match of the filename as already
held in the global $current::page variable and return its index
number. In the unlikely event no match is found, return a fixed
string, e.g. "404.html".

AFAIK there's no smart way to do that. So a standard linear loop and you
even have to maintain the index yourself.
3) Extract the string in %location_de that has the same index number
as in %location_en. But I guess this must be a too simple question....

The 'index' in a hash is more commonly called the key.
Therefore, if your 'index' into %location_en is "foobar" then just use
$location_de{foobar}

jue
 
M

Mumia W.

[...]
Instead of opting for a more sophisticated multi-dimensional hash array
method as disussed in previous posts of this string, I guess another and
possibly easier solution would be simply to copy the keys into a standard
array, and then use index numbers to identify the mirror pages of the other
language version.

For now I have something as follows:

use Tie::IxHash;

tie my %location_en, "Tie::IxHash";
tie my %location_de, "Tie::IxHash";

$current::page = $ENV{DOCUMENT_NAME} || 'undefined';

%location_en = ('page1.html' => 'page one',
'bla.html' => 'blabla',
'something.html' => 'Something');

%location_de = ('seite1.html' => 'Seite eins',
'blau.html' => 'Blau',
'ding.html' => 'Ding');

So to utilise the existing data, as opposed to maintain hashes and arrays
with partly duplicate data, I'd like to:

1) Copy the keys, i.e. the page URL's or filenames from %location_en into
an normal array where I can easier refer to them by index.

Exactly how would "page1.html", "bla.html"
and "something.html" be placed
in a standard array named @location_en. A simply question
I know...


my @location_en = keys %location_en;

But why would you want to do this? By tying to Tie::IxHash,
you already have the equivalent of an array (if you save the
object returned by "tie").

my $obj_en = tie my %location_en, "Tie::IxHash";
my $obj_de = tie my %location_de, "Tie::IxHash";
2) Search the array for a possible match of the filename as already held in
the global $current::page variable and return its index number. In the
unlikely event no match is found, return a fixed string, e.g. "404.html".

Umm, why would you want to search an array when you already
have something better?

my $match_index = $obj_en->Indices($current::page);
my $string = defined $match_index ? $match_index : "404.html";
4) Extract the string in %location_de that has the same index number as in
%location_de. But I guess this must be a too simple question....

In any case, thank you for any helpful pointers, especially regarding
question #1 and #2.

my $string = $obj_de->Keys($match_index);


P.S.
I think that a multi-dimensional hash/array would be easier:

my %lg = (
en,pages => [ 'page1.html', 'bla.html', 'something.html' ],
en,text => [ 'pageone', 'blabla', 'something' ],

de,pages => [ 'seite1.html', 'blau.html', 'ding.html' ],
de,text => [ 'Seite ens', 'blau', 'Ding' ],

);

$; = ',';

my %lgn;
foreach my $x (grep /,pages$/ keys %lg) {
foreach my $y (0..$#{$lg{$x}}) {
my $aref = $lg{$x};
$lgn{"$aref->[$y]"} = $y;
}
}

# Answer Q1: No need. @{ $lg{'en,pages'} } is already an array.

# Answer Q2:
my $match_index = $lgn{$current::page};


ALL CODE UNTESTED
 
F

Franzl Wisseworst

Mumia W. wrote:

[..]
my $match_index = $obj_en->Indices($current::page);
my $string = defined $match_index ? $match_index : "404.html";

Many thanks for posting this untested bit of code, it works like magic!
I think that a multi-dimensional hash/array would be easier:

I have an itching feeling that you're right. The looping procedures of the
multi-dimensional hash/array are however a bit hard for me to swallow, and
so I think the above solution will serve its purpose for the time being,
while the below example goes on my pinboard reserved for a future purpose,
mainly because I need to half understand the code before I can maintain it.

Thanks for the excellent code!
my %lg = (
en,pages => [ 'page1.html', 'bla.html', 'something.html' ],
en,text => [ 'pageone', 'blabla', 'something' ],

de,pages => [ 'seite1.html', 'blau.html', 'ding.html' ],
de,text => [ 'Seite ens', 'blau', 'Ding' ],

);

$; = ',';

my %lgn;
foreach my $x (grep /,pages$/ keys %lg) {
foreach my $y (0..$#{$lg{$x}}) {
my $aref = $lg{$x};
$lgn{"$aref->[$y]"} = $y;
}
}

# Answer Q1: No need. @{ $lg{'en,pages'} } is already an array.

# Answer Q2:
my $match_index = $lgn{$current::page};


ALL CODE UNTESTED
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top