4

I got a json array like below:

[
    {"value":"uk-icon-adjust","title":"Adjust","url":"#", "text":""},
    {"value":"uk-icon-adn","title":"Adn","url":"#", "text":""},
    {"value":"uk-icon-align-center","title":"Align center","url":"#", "text":""},
    {"value":"uk-icon-align-justify","title":"Align justify","url":"#", "text":""},
    {"value":"uk-icon-align-left","title":"Align left","url":"#", "text":""}
]

I want to search this json array for specific titles. But the problem is, that I want to search with a Regex. e.g: sb searchs for "ad" -> the function should return the first two json strings (Adjust and Adn).

I have no idea, now to setup a javascript function which can achieve this.

Some ideas?

Jamiec
  • 133,658
  • 13
  • 134
  • 193
Smeaven
  • 147
  • 3
  • 14

3 Answers3

6

Try this:

var array = [
    {"value":"uk-icon-adjust","title":"Adjust","url":"#", "text":""},
    {"value":"uk-icon-adn","title":"Adn","url":"#", "text":""},
    {"value":"uk-icon-align-center","title":"Align center","url":"#", "text":""},
    {"value":"uk-icon-align-justify","title":"Align justify","url":"#", "text":""},
    {"value":"uk-icon-align-left","title":"Align left","url":"#", "text":""}
  ],
  searchString = 'ad',
  searchRegExp = new RegExp(searchString , 'i'); // 'i' makes the RegExp ignore case

var result = array.filter(function(e){ // Filter out any items that don't pass the
    return searchRegExp.test(e.title); //  RegExp test.
});

Result:

[
    {"value":"uk-icon-adjust","title":"Adjust","url":"#","text":""},
    {"value":"uk-icon-adn","title":"Adn","url":"#","text":""}
]

If you only want an array of titles, you can then map the result, like this:

var titles = result.map(function(e){
    return e.title;
});

Titles:

["Adjust", "Adn"]

You'll want to do this mapping after filtering the array, for efficiency. This way you'll only have to iterate over the filtered result, instead of first iterating over all items to get the titles, then iterating over all of them again to filter them.

Of course, this can be combined with the filtering:

var result = array.filter(function(e){
    return searchRegExp.test(e.title);
}).map(function(e){
    return e.title;
});

Please keep in mind that both Array.prototype.filter() as Array.prototype.map() Aren't supported in IE 8 or lower. However, the pages I linked to do have some polyfills to make these functions work in older versions of IE.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • how about, if I have the json array to search in a extern json file? I tried it this way: `var array = $.getJSON(url);` but then the filter function not works? – Smeaven Dec 12 '14 at 16:36
  • @Smeaven: That's because `getJSON` is asynchronous. [See this question.](http://stackoverflow.com/questions/15764844/jquery-getjson-save-result-into-variable) – Cerbrus Dec 12 '14 at 16:43
3

That's an native Object. You can do it this way though, by first creating an Array of titles by using Array.map and then filter them using Array.filter

var titles = obj.filter(function(o){
   return /^ad/i.test(o.title);
}).map(function(o){ return o.title; });
Amit Joki
  • 58,320
  • 7
  • 77
  • 95
  • It'd be more efficient to use `filter` before `map`. – Cerbrus Dec 12 '14 at 15:05
  • 1
    @Cerbrus I think it's *micro-optimization*. I've not heard it before. Would love to see links stating so. Honestly – Amit Joki Dec 12 '14 at 15:07
  • Assume you have an array of 100 items: Map->Filter iterates over 100 items twice, always resulting in 200 iterations. Filter->Map first iterates (filters) over 100 items, then iterates over the remaining items. More often than not, this will result in less than 200 iterations. Just because something is a _"micro-optimization"_ doesn't mean it's a bad idea to think about what your code is actually doing on what kind of data. – Cerbrus Dec 12 '14 at 15:09
2

Amit Joki answer is the answer.
If you don't want to use map(), you could also try:

var json = [
    {"value":"uk-icon-adjust","title":"Adjust","url":"#", "text":""},
    {"value":"uk-icon-adn","title":"Adn","url":"#", "text":""},
    {"value":"uk-icon-align-center","title":"Align center","url":"#", "text":""},
    {"value":"uk-icon-align-justify","title":"Align justify","url":"#", "text":""},
    {"value":"uk-icon-align-left","title":"Align left","url":"#", "text":""}
];

function search(array, re) {
    var regexp = new RegExp(re, 'gi');
    for (var i = 0; i < array.length; i++) {
        return array[i].title.match(regexp);
    }
    throw "Couldn't find object like " + re;
}

console.info(search(json, 'ad'));
MarcoS
  • 17,323
  • 24
  • 96
  • 174