Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Background

I have an Array of data in a result object returned by an Ajax call. The data looks like this:

{ Name="User1 Name1", FirstName="User1", Id="005400000001234567", more...}
{ Name="User2 Name1", FirstName="User2", Id="005400000001234568", more...}

Where each item looks like this:

{
    Id:"005400000001234567",
    Name:"User Name",
    FirstName:"User",
    LastName:"Name",
    Title:"Manager"
}

Question

I want to be able to retrieve data either by Id (returning a single user) or by Title (returning an array of users). What would be the best way to go about doing that using JavaScript or jQuery?

Example

Here's what I've attempted so far:

function GetAllUsers()
{
    AllUsersById = new Object();

    MyClass.MyAjaxMethod(function(result,event) {
        if(result) { 
            j$(result).each(function(index,item)
            {
                AllUsersById[item.Id] = item;
            });
        }
    });
}

The code I have above is great for indexing by Id, but I'm not sure what to do for Title.

Additional Details

Also, by the way, there are about 1000 records, and I need this to be fairly efficient. (This is one of the reasons I'm getting the data right away, when the document is ready. I'm not an expert on JavaScript or jQuery efficiency, though. Let me know if you have a better way.)

Any ideas? Thanks in advance!

share|improve this question
    
do you need this to be all one array, or could you build two - one for index by #, one for grouped by title. –  circusdei Feb 14 '12 at 20:34
1  
It can be two arrays. –  Matt K Feb 14 '12 at 20:34
add comment

4 Answers

up vote 5 down vote accepted

Seems like you're looking for .grep(). Using .grep you could create a generic function that would filter:

function findInJson (json, key, value) {
    return $.grep(json, function (obj) {
        return obj[key] == value;
    });
}

// With your data getting a specific user by id
findInJson(yourJSON, "Id", "005400000001234567");

// Getting a set of users by title
findInJson(yourJSON, "Title", "Manager");
share|improve this answer
    
I noticed in the jQuery reference "The $.grep() method removes items from an array as necessary so that all remaining items pass a provided test." Does grep actually modify the array it's searching through? –  Matt K Feb 14 '12 at 20:44
    
@MatthewKeefe grep will not change the object that you're searching through. –  sinemetu1 Feb 14 '12 at 20:46
    
Wow, that's excellent. Very fast too! Thanks! –  Matt K Feb 14 '12 at 20:59
    
thanks a lot for this. :) God bless you. –  Asim Siddiqui Sep 19 '13 at 16:58
add comment

Create a constructor function vis-à-vis class that encapsulates this data, and you can ask it to find users by title, or id. To do a quick lookup, you can create two lookup tables - one for id, and another for title. Assuming a decent hash implementation, the lookups can be done in O(1) on the average. The initial computation is O(n), but lookups are faster. Also it uses slightly more space because we are creating two additional maps. For 1000 objects, that is not a problem. Again, if you will be doing a lot more lookups, this approach will be much faster.

Here's a simple implementation.

function Users(users) {
    this.idMap = {};
    this.titleMap = {};
    this.users = users;
    var me = this;

    users.forEach(function(user) {
        this.idMap[user.Id] = this.idMap[user.Id] || [];
        this.idMap[user.Id].push(user);

        this.titleMap[user.Title] = this.titleMap[user.Title] || [];
        this.titleMap[user.Title].push(user);
    }.bind(this));
}

Users.prototype.findByTitle = function(title) {
    return this.titleMap[title];
};

Users.prototype.findById = function(id) {
    return this.idMap[id];
};

To use it, create an object of Users passing it the AJAX response, and then query it using the findById and findByTitle methods.

var users = new Users(responseData);
users.findById("1");
users.findByTitle("SomeTitle");

Checkout a working example.

share|improve this answer
    
Fascinating. I learned a ton from your answer and example, thanks! However, I think I'll have to go with grep for simplicity. –  Matt K Feb 14 '12 at 21:28
add comment

If you have control over the data returned, it's better if you produce it with the following format:

var allUsers=[
{"005400000001234567":{
    Name:"User Name",
    FirstName:"User",
    LastName:"Name",`
    Title:"Manager"
}} 
,{"005400000001234568":{
    Name:"User2 Name2",
    FirstName:"User2",
    LastName:"Name2",
    Title:"Manager2"
}} 
/*..etc.. */
];

This way you avoid the loop ($(result).each()) inside GetAllUsers (which builds the array above). The search by title can be performed efficiently by building a second array of the form:

var byTitle=["title1":[0,1], "title1":[0,1], /*etc*/];

As you see, each title has a list of indexes to allUsers. Then you simply do:

var allManagers = [];
for(var i in byTitle["Manager"]) allManagers.push(allUsers[i]);
share|improve this answer
add comment

I think this should work. I really can't test it without your data.

function GetAllUsers()
{

AllUsersById = new Object();
AllUsersByType = new Object();

MyClass.MyAjaxMethod(function(result,event) {
    if(result) { 
        j$(result).each(function(index,item)
        {
            // By Id
            AllUsersById[item.Id] = item;

            // By Type
            if (!AllUsersByTitle[item.Title]) {
                AllUsersByTitle[item.Title] = new Array();
            }

            AllUsersByType[item.type].push() = item;
        });


    }
});
}
share|improve this answer
1  
Your first example worked when I grouped it all together in the first each loop and added: if (!AllUsersByTitle[item.Title]) { AllUsersByTitle[item.Title] = new Array(); } before the push. –  Matt K Feb 14 '12 at 20:53
    
edited. thanks for the corrections. –  circusdei Feb 14 '12 at 21:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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