1

I have an array of elements like this:

myArray = [{name:'john',age:25},
           {name:'marta',age:20},
           {name:'pedro',age:22}]

My program has to access an object by it's name several times a second. I defined this function:

function getPersonByName(name){
    for (var i=0; i<myArray.length; ++i)
        if (myArray[i].name == name)
            return myArray[i]
}
var john = getPersonByName('john');

But that loop running everytime seems inneficient. I could instead create a hash table associating the objects, and keep it updated:

var hash = {john:myArray[0], marta:myArray[1], pedro:myArray[2]}
var john = hash["john"]

But I don't know how the javascript's hash access is defined, so, is the second method actually faster?

5
  • 4
    Much, much, much, much faster. Commented Mar 17, 2012 at 12:20
  • I guess JavaScript arrays have a complexity similar to C++'s std::map, which uses red black trees. So it's O(log N) instead of O(N), and that's, as Pointy said, much, much, much faster. Commented Mar 17, 2012 at 12:21
  • Pointy so it's definitely worth creating the hash? Commented Mar 17, 2012 at 12:29
  • Felix, interesting. Zeta, I see! Commented Mar 17, 2012 at 12:30
  • If there are more than a few objects involved, then yes. It's also a lot simpler anyway. @Zeta I suspect that JavaScript object maps are implemented as hash tables and not red-black trees, but that's an internal detail of each interpreter and not required by the spec. Commented Mar 17, 2012 at 12:31

2 Answers 2

1

The easiest way to implement this would be to cache the result of the function as explained by John Resig at learning advanced javascript

Your function would look something like this

function getPersonByName(name){
    if (getPersonByName.cache[name]) {
        return getPersonByName.cache[name];
    } else {
       for (var i=0; i<myArray.length; ++i)
           if (myArray[i].name == name) {
               getElements.cache[name] = myArray[i];
               return getPersonByName.cache[name];
           }
    }
}

getPersonByName.cache = {};

var john = getPersonByName('john');

John Resig's stats from a few years ago recorded a performance increase of about 7 times using this method rather using direct DOM access, which is a technique that is integrated a lot in the JQuery library.

Sign up to request clarification or add additional context in comments.

2 Comments

Isn't this creating the hash that @Dokkat proposed, but on the run? Whether to create a hash beforehand or on the run, depends on your expected use. How computing intensive the process that does value retrieval inside the loop (DOM lookup is likely to take more time than array lookup)? How many elements will end up in the hash? How often do you expect to have to look up different users? There is no one size fits all solution. Best is to benchmark against expected scenarios.
Whether to create another representation of your data (hash derived from array) or not also depends on your expected uses. With DOM lookup, you expect to have to store only a few values among all possible in the original dataset (DOM). With a user database, you are likely to end up with as many entries as in the initial array. Benchmarking tools will help you understand trade offs.
1

Performance tests for different ways to loop through an array are available on jsPerf

According to these benchmarks, you would get a better performance with:

function getPersonByName(name){
  for (var i<myArray.length; i--;)
    if (myArray[i].name == name)
      return myArray[i]
 }

There may be an extra benefit from storing myArray[i] in a variable to avoid to have to look it up multiple times. Just be careful to declare that variable outside of the loop.

function getPersonByName(name){
  var obj;
  for (var i<myArray.length; i--;)
    obj = myArray[i];
    if (obj.name == name)
      return obj;
 }

Another benchmark on jsPerf suggests that array is faster than object.

None of the benchmarks quite replicate your use. You could create a custom test on jsPerf. If you don't want to register there, you can use the quickbenchmark demo on jsdoit or download one of the many performance/benchmarking javascript libraries. Run a search for benchmark on github to locate them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.