Return index in 1 of 2 arrays if match is found

F

Fred

I'd like to return a match and its index number in one of two arrays that
matches the filename within:

var menuURLs = new Array

("dinner.html",
"lunch.html",
"drinks.html");

var headerURLs = new Array

("partyservice.html",
"deliveries.html",
"reservation.html");

The following code cycles through the menuURLs array and compares it with
"file" (the filename of the html page):

var i = menuURLs.length;
while (i-- && menuURLs !=file){}
var currentIndex = (i<0)? 0 : i;

This works fine and returns the current index of the array if a match is
found. If the filename does not match any current page name, it still
returns "0" however. Instead, and what I would like is that the search
continues into the next array in case it fails to find a match in the first:

var i = headerURLs.length;
while (i-- && headerURLs !=file){}
var currentIndex = (i<0)? 0 : i;

In either cases I'd like to return an index number as well the array name
in which it was found, but only if a match returns, otherwise it should
return false. There will never exist a same filename string in both arrays.

Anyone has any idea how to most easily do this?
 
R

RobG

Fred said:
I'd like to return a match and its index number in one of two arrays that
matches the filename within:

var menuURLs = new Array

("dinner.html",
"lunch.html",
"drinks.html");

You may find it easier to initialise the array as:

var menuURLs = [
"dinner.html",
"lunch.html",
"drinks.html"
];

Since you have two (or more) arrays that you want to cycle through, one
solution is to put the arrays into an object:

var urlObj = {
menuURLs : [
"dinner.html",
"lunch.html",
"drinks.html"
],
headerURLs : [
"partyservice.html",
"deliveries.html",
"reservation.html"
]
}

and pass a single object reference.

[...]
The following code cycles through the menuURLs array and compares it with
"file" (the filename of the html page):

var i = menuURLs.length;
while (i-- && menuURLs !=file){}
var currentIndex = (i<0)? 0 : i;


That's not too clever, if the while loop doesn't find a match it will
return '0', so you don't know if you found a match at zero or not
(unless you make the first array entry some dummy value and therefore
know that it's an error - not a good idea).

Better to loop through the elements of the array and return 'i' when a
match is found. If none is found, return something that you *know*
means one wasn't found, say null or undefined:

function getIndex(aName, fName)
{
for (var i=0, len=aName.length; i<len; i++){
if (aName == fName) return i;
}
return null;
}


A for loop will be just as fast as a while loop and they are usually
easier to maintain. Call it with something like:

var currentIndex = getIndex(arrayName, fileName);
if ( null == currentIndex ){
// didn't find the filename in the array
}

You could also test if 'number' == typeof fIndex if you don't want to
return null explicitly from the getIndex function.

This works fine and returns the current index of the array if a match is
found. If the filename does not match any current page name, it still
returns "0" however. Instead, and what I would like is that the search
continues into the next array in case it fails to find a match in the first:

var i = headerURLs.length;
while (i-- && headerURLs !=file){}
var currentIndex = (i<0)? 0 : i;

In either cases I'd like to return an index number as well the array name
in which it was found, but only if a match returns, otherwise it should
return false. There will never exist a same filename string in both arrays.


If you use the suggested object to store the arrays, you can pass a
reference to the object and the URL to match to the function:

function getMatch(obj, url)
{
var currentIndex, aName;

for (aName in obj){
currentIndex = getIndex(obj[aName], url);
if ('number' == typeof currentIndex) break;
}

if ( null == currentIndex ){
// didn't find the filename in the array, deal with it
alert('Didn\'t find it');

} else {
// to get a reference to the array, use obj[aName];
alert('URL ' + url
+ ' is in array ' + aName
+ '\nIndex is ' + currentIndex);
}
}

// Call it with:
getMatch(urlObj,'reservation.html');


Alternatively, keep the arrays separate and pass each of them to a
function. If you want to remember the name of the array (which seems
pointless[1]) you need to pass the names as a strings, then use them to
get a reference to the array. Pass the filename to match as the first
parameter so you know which one it is:

function findFile()
{
var fArray, nList = arguments;
var aIndex, aName;
var file = nList[0];

for (var i=1, j=nList.length; i<j && 'number'!=typeof aIndex; i++){
fArray = window[nList];

for (var m=0,n=fArray.length;m<n && 'number'!=typeof aIndex; m++){
if (fArray[m] == file){
aName = nList;
aIndex = m;
}
}
}

if (aName){
alert('Array name is ' + aName
+ '\n' + file + ' is index ' + aIndex);
} else {
alert(file + ' not found.');
}
}


And call it with:

findFile('partyservice.html', 'menuURLs', 'headerURLs')


You can add as many arguments as you like, the object method seems much
simpler to me.

1.
Keeping the name of the matched array seems useless because it is only a
variable name, it has no real use. There can be many, many references
to the same object. If you want to use that array for something else,
pass a reference to it rather than the name as a string. Then it can
appear in any context (say either as a global object or as a property of
some other object) and your downstream function doesn't care what the
'access chain' is:

window[arrayName];
window[objectName][arrayName];
objectRef[arrayName];

and so on.
 

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,780
Messages
2,569,608
Members
45,247
Latest member
crypto tax software1

Latest Threads

Top