2

I need to search an array of objects with an object of search terms and get the index of results in an array.

Let's say I have an array like this:

[
  {
    name: "Mary",
    gender: "female",
    country: "USA",
    orientation: "straight",
    colorChoice: "red",
    shoeSize: 7
  },
  {
    name: "Henry",
    gender: "male",
    country: "USA",
    orientation: "straight",
    colorChoice: "red",
  },
  {
    name: "Bob",
    colorChoice: "yellow",
    shoeSize: 10
  },
  {
    name: "Jenny",
    gender: "female",
    orientation: "gay",
    colorChoice: "red",
  }
]

Now I need to search the array for:

{
  gender: "female"
}

and get result:

[ 0, 3 ]

The search object can be any length:

{
  gender: "female",
  colorChoice: "red"
}

What's the cleanest and most performant way to search the array?

Thanks.

Charles
  • 48,924
  • 13
  • 96
  • 136
Harry
  • 47,045
  • 66
  • 163
  • 243

2 Answers2

2

This should do the trick:

function searchArray(fields, arr)
{
    var result = [];            //Store the results

    for(var i in arr)           //Go through every item in the array
    {
        var item = arr[i];
        var matches = true;     //Does this meet our criterium?

        for(var f in fields)    //Match all the requirements
        {
            if(item[f] != fields[f])    //It doesnt match, note it and stop the loop.
            {
                matches = false;
                break;
            }
        }

        if(matches)
            result.push(item);  //Add the item to the result
    }

    return result;
}

For example:

console.log(searchArray({
  gender: "female",
  colorChoice: "red"
},[
  {
    name: "Mary",
    gender: "female",
    country: "USA",
    orientation: "straight",
    colorChoice: "red",
    shoeSize: 7
  },
  {
    name: "Henry",
    gender: "male",
    country: "USA",
    orientation: "straight",
    colorChoice: "red",
  },
  {
    name: "Bob",
    colorChoice: "yellow",
    shoeSize: 10
  },
  {
    name: "Jenny",
    gender: "female",
    orientation: "gay",
    colorChoice: "red",
  }
]));
TJHeuvel
  • 11,562
  • 3
  • 35
  • 46
  • You can edit the function to return the indexes (i) of the array too, just push that on the results array instead of the item. – TJHeuvel Apr 21 '11 at 08:28
2

Here's the idea:

function getFemales(myArr){
 var i = myArr.length, ret = [];
 while (i--){
  if ('gender' in myArr[i] && myArr[i].gender === 'female') {
    ret.push(i);
  }
 }
 return ret.sort();
}

see jsfiddle

And more generic:

function findInElements(elArray, label, val){
 var i = elArray.length, ret = [];
 while (i--){
  if (label in elArray[i] && elArray[i][label] === val) {
    ret.push(i);
  }
 }
 return ret.sort();
}

see jsfiddle

KooiInc
  • 104,388
  • 28
  • 131
  • 164
  • Any reason you traverse the array in reverse? – TJHeuvel Apr 21 '11 at 08:37
  • 2
    It's quicker.See http://devpro.it/examples/loopsbench/ or http://codeutopia.net/blog/2009/04/30/optimizing-javascript-for-extreme-performance-and-low-memory-consumption/ – KooiInc Apr 21 '11 at 08:47
  • Thats pretty damn clever, since the type juggeling makes sure the while stops when i <= 0! You'd have to change your i-- to --i though :) – TJHeuvel Apr 21 '11 at 09:05
  • using --i I would miss element 0. In that case I'd have to use `(--i>=0)`. It's not significantly faster, see http://jsperf.com/loop-descendening – KooiInc Apr 21 '11 at 09:12