3
\$\begingroup\$

Based on input from the UI (most likely a string) I would like to search a list of object and return all object that has one or more matching property values which match the given input.

Do you have any thoughts regarding performance or overall design?

The only requirement is that I need to keep the outer Array.prototype.filter. My question is how/if I should modify anything inside its callback.

var items = [{ x: 1, y: 2 }, { x:1, y: 3, z: 'blah' }];

function findObjectByPropertyValue(value, ignoreCase){

    var result = items.filter(function(item){

       var keys = Object.keys(item);
       for(var i = 0, len = keys.length; i < len; i++){

           var match, 
               propertyValue = item[keys[i]];

           if(ignoreCase && typeof propertyValue === 'string' && typeof value === 'string')
               match = propertyValue.toLowerCase() === value.toLowerCase();
           else
               match = propertyValue === value;

           if(match)
               return true;
        }   
    });

    return result;
}

console.assert(findObjectByPropertyValue(1).length === 2);
console.assert(findObjectByPropertyValue(2).length === 1);
console.assert(findObjectByPropertyValue(4).length === 0);
console.assert(findObjectByPropertyValue('blah').length === 1);
console.assert(findObjectByPropertyValue('Blah', true).length === 1);
console.assert(findObjectByPropertyValue('Blah').length === 0);

http://jsfiddle.net/Lg6rwnwh/1/

\$\endgroup\$
1
\$\begingroup\$

The method console.assert is a non-standard feature and it may not work across different user's browsers as each browser may have a different implementation, or may not have implemented it at all.

Read more at the red box at the top of this Mozilla Developer Network article.

I'd say you are better off using console.log because most browsers implement that, and use the same base implementation.


var keys = Object.keys(item);
for(var i = 0, len = keys.length; i < len; i++){

This is slightly re-inventing the wheel.

JavaScript already has a type of loop called for/in loop. It's syntax is this:

for(var key in object) {

}

Where key is a variable that will iterate through all the properties/keys of object. You could then access the value of that key/property by using

object[key]

withing the loop.


Instead of hard-coding the array items as the array that your function is checking, write over Array.prototype with this as a new method.

Then, you can refer to the array to check as this.

Here is roughly what I mean:

Array.prototype.findObjectByPropertyName(value, ignoreCase) {
    var result = this.filter(...);
    ...
}

Then, if you wanted to use this function on items, you would simply call (for example):

items.findObjectByPropertyName('blah', true);

if(ignoreCase && typeof propertyValue === 'string' && typeof value === 'string')
     match = propertyValue.toLowerCase() === value.toLowerCase();
 else
     match = propertyValue === value;

This is a debatable topic; many will say that you should always have {}s no matter how short the code inside the block will be.

I believe they say this because it greatly improves the readability of the organization of your code because all the code that is associated with, for example, that if statement is clearly seen in between the {}s.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.