Wherefore Art Thou Challenge

Hey everyone,

I just submitted the code for Wherefore Art Thou challenge and, after a lot of thinking, I came up with two solutions to this problem and I want to share some thoughts with you guys.


Ok. So the first solution I found was the least “elegant” code, but more intuitive to me. I used a filter() function, a for…in loop and some ternary operators in 10 lines of code. Here you have it:

function whatIsInAName ( collection , source ) {
  return collection.filter( obj => {
    let match = false;
    for ( const sourceKey in source )
      match =  obj.hasOwnProperty( sourceKey )
            && source[sourceKey] == obj[sourceKey]
            ?  true : false;
    return match ? obj : null;
  } );

Then I wanted to do it another way, to reduce the number of lines, to try more “functional programming” (map, reduce, etc), and to see it from another perspective. I used filter(), map() and reduce() functions in 7 lines after some time reading examples:

function whatIsInAName ( collection , source ) {
  return collection.filter( obj => {
    return Object.keys( source )
      .map( key => obj.hasOwnProperty( key ) && source[ key ] === obj[ key ] )
      .reduce( ( accum , currItem ) => accum && currItem );
  } );

So far so good. BUT, I wanted to know how good they both performed in terms of speed, I found out that the first solution executes faster (actually way faster, more than half the time):

1st solution: 0.5 milliseconds.
2nd solution: 0.19999999999998863 milliseconds.

What do you think about this? Maybe I didn’t do enough tests? I’d like to know your opinion on the matter because, at least in this case, I find easier to read my first solution and it turns out to be also faster.

Happy coding!

First of all, please blur any full solutions to challenges. I have blurred them out for you, but in the future, please surround your code with [spoiler] and [/spoiler] tags.

Secondly, I do not know what data you used to test each solution or how times you repeated the tests to calculate a time number (shown above). Also, does each number above represent an average time for multiple tests of the same solution with the same data?

You state the 1st solution is faster, but based on the data you have shown above, the 2nd solution is faster, because 0.19999999999998863 milliseconds is less than 0.5 milliseconds.

If you can provide more details of how you performed the tests (data used, number of repetitions, results of those repetitions, etc…), we would have more to evaluate.

Eh? 0.2 is less than 0.5. Anyway, mostly these benchmarks are pretty irrelevant but if you really want to compare then compare an imperative with a functional approach (just loops, not higher order functions), there’s barely any difference between these two

1 Like

Sorry, I didn’t know about that tag :slight_smile:

I did the tests with this and I placed the wrong numbers (0.5 was the second solution hehe. I tested it with the provided examples by the challenge only, but most of them outputs similar results.

I just found the results interesting. Only ten lines of code, but maybe a huge number of lines can make a difference.

Number of lines won’t make much difference, it’s how the code executes that makes the difference. A for loop solution is [probably] always going to be faster, as is [probably] not creating anything on the fly. “Probably” because it’ll depend on how the specific JS engine works - older engines will only have an interpreter, but newer engines compile the code, and are pretty good at automatically inlining things. 0.5ms and 0.2ms is a tiny, tiny difference; the first takes twice long as the second on one particular engine under one particular set of system specs, but the numbers are so small that it’s difficult to read anything meaningful from one test.

Edit: be very careful about optimizing JS unless you really need to (eg you are writing a virtual DOM implementation, or you have some game logic that is performance critical); there is lots of advice and afaics most of it is wrong due to constant improvements in JS engine technology. V8 (the engine that powers Chrome and Node), for example, does not have an interpreter. Instead, it has two compilers: the first takes your JS code and converts it to unoptimized machine code. If there is something that prevents optimization, it stays as that. But if not, the second compiler, which optimizes the machine code for speed, can be run. Examples of stuff that prevents optimization: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers