Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find nested object by value and return the found objects key

Tags:

javascript

This has probably been asked quite a few times before but I'm having trouble finding a decent solution.

I have the JSON result of a mongo query kinda resembling this:

var data = [{ _id: 123, name: "Test"}, { _id: 124, name: "Test2" }]

This is a very simple version of the data I have, I need to be able to find and object in the array that matches the "_id" property something like

data.find({ _id: 123 }); // returns 0
data.find({ _id: 124 }); // returns 1

If anyone knows a good solid solution to this it will be greatly appreciated.

Updated:

I've used the answer provided by @Rocket Hazmat to create a neat little module for angular. Since I'm working with objects I wanted a way to query the json in a similar way to mongo.

angular.module("myModule").factory("obj", function() {
    return {
        findKey: function(query, data) {
            for (var i = 0, l = data.length; i < l; i +=1) {
                var item = data[i],
                    match = true;
                // Check each object
                for (var x in query) {
                    if (item[x] !== data[x]) {
                        match = false;
                        break;
                    }
                }
                // Did it match ?
                if (match) {
                    return i;
                }
            }
            return false;
        }
    }
});

I can then use this in my controllers:

angular.module("myModule")
    .controller("mainCtrl", ["$scope", "obj", function($scope, $obj) {
        // This would be the result of an ajax request
        $scope.people = [
            { _id: 1, name: "Test1" },
            { _id: 2, name: "Test2" },
            { _id: 3, name: "Test3" }
        ];

        $obj.findKey({ _id: 1, name: "Test1" }, $scope.people); // 0
        $obj.findKey({ _id: 2 }, $scope.people); // 1
        $obj.findKey({ name: "Test2"}, $scope.people); // 1
        $obj.findKey({ _id: 3, name: "Test3" }, $scope.people); // 2
        $obj.findKey({ _id: 3, name: "Test1" }, $scope.people); // false
    }]);

This would be buried deep inside a large application and I needed a fast way to get the key of the item so I can easily manipulate the scope

like image 993
Jon Watkins Avatar asked Oct 04 '22 03:10

Jon Watkins


2 Answers

You're gonna need to loop through the array and compare each object to see if it contains the key(s) you're looking for.

Here's something I hacked up quickly.

Array.prototype.find = function(obj){
    // Loop through array
    for(var i = 0, len = this.length; i < len; i++){
        var ele = this[i],
            match = true;
        // Check each object
        for(var x in obj){
            if(ele[x] !== obj[x]){
                match = false;
                break;
            }
        }
        // Did it match?
        if(match){
            return i;
        }
    }
};

Then just run it like you have shown:

data.find({ _id: 124 }); // 1
like image 152
Rocket Hazmat Avatar answered Oct 12 '22 10:10

Rocket Hazmat


You can extend Array object with new functionality by adding a function to the Array.prototype, and you can use this to refer the the owner which calls the function.

Inside the find() method, you can utilize filter() function to filter the collection.

var data = [{ _id: 123, name: "Test"}, { _id: 124, name: "Test2" }]

Array.prototype.find = function(obj){
    return this.filter(function(item){
        return (item._id === obj._id);
    });
}

var result = data.find({_id: 123});
like image 39
zs2020 Avatar answered Oct 12 '22 12:10

zs2020