2

For example, i have an array like this:

var arr = [
    {"keyword": "Sample 1", "item": {"title":"Sample Title", "url": "/sample"}},
    {"keyword": "Foo 1", "item": {"title":"Foo Title", "url": "/sample"}}
];

I want to search in the "keyword" key, like when a user presses a key from their input and return that matches objects.

If user presses to "s" key, then first [0], element must return. Like using the SQL LIKE statement.

$("#query").on('keypress', function () {
    var result = $.grep(keywords, function(e){
    //I do not know what should i do here.    
    });
});

5 Answers 5

3

If you want to use $.grep you can do it like this:

$("#query").on('keyup', function() {
    var search = this.value.toLowerCase();
    var result = $.grep(keywords, function(el) {
        return el.keyword.toLowerCase().indexOf(search) > -1;
    });
});

Demo: http://jsfiddle.net/9TPSa/

Also note, that I switched to keyup event to be able to read updated this.value.

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

7 Comments

It does loop though, @R.CanserYanbakan, so if you wanted to avoid that: you don't when using $.grep().
It should loop through all the elements in order to find all matching rows. But in order to improve performance I would also recommend using native for-loop better.
Which makes it exactly as efficient as looping manually, just more convenient (but, yes, it does do the latter). SO if there really are ~1000 objects in that array (as stated in a comment on my answer), it's really not a great thing to do, especially not every time. As jQuery is written in Javascript tiself, you don't even habe the speed-advantaqge of native code (Array.prototype.filter, as suggested by @tewathia, has this).
That's why I said If you want to use $.grep .... I think OP will figure out what approach is better for him. He has good alternatives. I just provider my $.grep answer.
@R.CanserYanbakan Then change to return el.keyword.toLowerCase().indexOf(search) == 0;. 0 means occurence position, very first letter.
|
1

Use the Array.prototype.filter method:

Array.prototype.filterBy = function(attr, value) {
    return this.filter(function(elem){
        return elem[attr].indexOf(value) !== -1;
    });
}

Then arr.filterBy('keyword', '1') would return both the objects(in your arr array), while arr.filterBy('keyword', 'oo') would return only the second one.

DEMO

1 Comment

I'v tried this but did not worked. Am i missing something? Can you please make an working example with inputs for me and people searching answers for like me? If we look above examples, there are performance issues may caused.
1

The answer is simple: YOu have to loop through all of your objects, look at each keyword entry and decide wether it matches your search or not. SOmething like this:

var results = [];
for (var i = 0 ; i < arr.length ; i++) {
    if (arr[i].keyword == "what ever you are looking for") {
        results.push(arr[i]);
    }
}

If you only need the frist match (and not all of them), you can simplify it:

var result;
for (var i = 0 ; i < arr.length ; i++) {
    if (arr[i].keyword == "what ever you are looking for") {
        result = arr[i];
        break;
    }
}

If you're not looking for equality, but need to use placeholders, take al look at String.prototype.indexOf() or regular expressions.

If you want to use $.grep() at all costs (there isn't too much difference to looping manually though, it does loop as well, just itnernally), you can - it'd look like this:

$("#query").on('keypress', function () {
    var result = $.grep(keywords, function(e){
        return (e.keyword == "whatever you are looking for again");
        // use regular expressions or .indexOf again if you don't want to test equallity
    });
});

Looping over large strucutres however (as you're comparing to databases, I suspect you have A LOT of those objects inside arr?) is very inefficient however. The fact that you HAVE TO loop indicates bad design. If you really got a lot of them, you might consider using a data structure that supports indexing, like a Hash Table/Map (those are not implemented in the core Java API; but are easy to implement on yoru own). They won't work if you need placeholders though, they're only an advantage when using equality to match results.

4 Comments

Looping is a bad idea in this case. The array has 1000~ objects. I will check for hash table thank you for information.
See eidt: $.grep does loop as well, so does Array.prototype.filter and any other method that filters an array/collection/whatever.
You are right but i don't want to do that myself :) Sorry.
"That" is "implementing a HashTable (or any other search-optimized data strucutre - there are more)? If so, I bet there are libraries that support those, I just don't know any. Google might ;) The only altnerative to this is looping (one way or another).
1

You could try using jQuery UI's AutoComplete... http://jqueryui.com/autocomplete/

You'll have to reduce your array to just the fields you're wanting to be searchable (ie. string literals for the keyword property, like ["Sample 1", "Foo 1"]) and pass that as the source in the autocomplete options.

Then hook into the change event http://api.jqueryui.com/autocomplete/#event-change and pull out the rest of your object from the original array.

EDIT : If you want to use grep, here is an example that gets the results using that method, but how you display them as auto options is then the next step!

http://jsfiddle.net/eQp3h/

var arr = [
    {"keyword": "Sample 1", "item": {"title":"Sample Title", "url": "/sample"}},
    {"keyword": "Foo 1", "item": {"title":"Foo Title", "url": "/sample"}}
];


$("#query").on('keyup', function () {
    var regExp = new RegExp("^" + $(this).val(), "i");

    var result = $.grep(arr, function(e, i){
        var match = regExp.test(e.keyword);
        return match;
    });

    $("#results").text(JSON.stringify(result));
});

4 Comments

Yes. I think this but i dont want to reduce my array firstly. I want to do this with functions like grep.
Fair enough, although it might be more efficient to perform some kind of reduce first, otherwise you'll be processing with every keypress which might need consideration :)
Yes. I understand. Maybe i will reduce my array later but first i need to learn how to do this :) Thank you!
just edited with an example of using grep, you have to return true or false from the callback function, which will be called on each element of your array. So here I'm just checking the element to see if the start of the string matches what has been typed in. Good luck!
0

Try this

    $("body").on("keyup","#query",function(e){
        var str = $("#query").val().toLowerCase();
        var newarr = $.grep(arr,function(n,i){
            return n.keyword.toLowerCase().search(str)!=-1;
        });
    });

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.