How do I avoid looping through multiple arrays
Unless I'm missing something, you could use a Javascript object as a dictionary (or a Map), in order to get the element id directly:
const idByPage = {
foo1: 1, foo2: 1, foo3: 1, foo4: 1,
bar1: 2,
bar2: 3,
bar3: 4
}
var page = 'bar2';
if (idByPage.hasOwnProperty(page)) {
console.log('element' + idByPage[page]);
// Add class to ('element' + idByPage[page])
// ...
}
Yes, however, this is really not necessary. O(n) operations, as you depict, aren't desirable targets for refactoring and constitute micro-optimizations. As such, this will more than likely harm readability at the insignificant gain of skipping a few instructions.
Here is how you would do it:
const arrCommon = ['foo1', 'foo2', 'foo3', 'foo4'];
const arrOther = ['bar1', 'bar2', 'bar3'];
const activeUrl = window.location.href;
const activePage = activeUrl.substring(activeUrl.lastIndexOf('/') + 1);
for(let i = 0, m = Math.max(arrCommon.length,arrOther.length); i < m; i++){
if(activePage == arrCommon[i]){
//if 'foo1, foo2 foo3 or foo4' add class to element 1
// search complete
break;
}
if(activePage == arrOther[i]){
//if 'bar1' add class to element 2
//if 'bar2' add class to element 3
//...
// search complete
break;
}
}
Addendum
It was raised in the comments that this approach results in more instructions executed. Indeed, because of the conditional short circuit this did execute more instructions in the given scenario, although only barely. In the example given by the OP it executes one extra instruction..... But still, the main point was to end up at O(n), which this is, and combine the multiple loops into one loop. Using a break
here will still be O(n) but the combined loop will end up less instructions on average. In addition, the undefined check can be removed to reduce instructions. This is now faster for essentially every scenario in this design; if we were to be examining the situation where exceptionally large sets of lookups were in place, a different approach would be more applicable, but this is rather contained.
There is also the opportunity to use an O(1) lookup as shown in other answers, which still require O(n) setup so long as arrays are involved (creating the comparisons as an object would allow O(1) lookup and not require a mapping from the arrays). Without changing the definition of the items, that is not necessarily optimizing this any more than O(n), but is at least decent to read when composed properly.
Overall, this type of discussion is the exact reason why micro optimizing your code is a bad idea. It wastes time and effort at the most minimal of gain.
Refactoring
Refactoring into a form which would allow O(1) execution from the original design would result in the most performance, albeit not needed in this case as noted above with micro optimizations. This is solely as an aside.
const activePage = 'foo3';
const commonStyles = {};
commonStyles.foo1 = commonStyles.foo2 = commonStyles.foo3 = commonStyles.foo4 = function(){
// add class to element 1
console.log('common');
};
const otherStyles = {};
otherStyles.bar1 = otherStyles.bar2 = otherStyles.bar3 = function(){
//if 'bar1' add class to element 2
//if 'bar2' add class to element 3
//...
console.log('other');
};
(commonStyles[activePage]&&commonStyles[activePage](),otherStyles[activePage]&&otherStyles[activePage]());
To avoid O(n) iterations, use a Set
or Map
instead, which should have "sublinear" lookup time - typically O(1).
const setCommon = new Set(['foo1', 'foo2', 'foo3', 'foo4']);
const mapOther = new Map(['bar1', el2], ['bar2', el3], ['bar3', el4]]);
const activeUrl = window.location.href;
const activePage = activeUrl.substring(activeUrl.lastIndexOf('/') + 1);
if (setCommon.has(activePage)) {
...
}
if (mapOther.has(activePage)) {
let el = mapOther.get(activePage);
...
}