最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Query array of objects in JavaScript - Stack Overflow

programmeradmin0浏览0评论

I have an array of coordinates like this:

coordinates = [
    {x: 1, y: 2},
    {x: 3, y: 4},
    {x: 5, y: 6},
    {x: 7, y: 8},
    {x: 9, y: 0}
];

I want to query this array for an object like this.

var searchFor = {x: 1, y: 2}

I tried this:

if ($.inArray(searchFor, coordinates) !== -1) {
       ...
}

But this always return -1. All I need is true/false info about whether the object is in this array. How can I achieve this?

I have an array of coordinates like this:

coordinates = [
    {x: 1, y: 2},
    {x: 3, y: 4},
    {x: 5, y: 6},
    {x: 7, y: 8},
    {x: 9, y: 0}
];

I want to query this array for an object like this.

var searchFor = {x: 1, y: 2}

I tried this:

if ($.inArray(searchFor, coordinates) !== -1) {
       ...
}

But this always return -1. All I need is true/false info about whether the object is in this array. How can I achieve this?

Share Improve this question asked Jun 27, 2013 at 12:22 BananaBanana 4,2389 gold badges37 silver badges49 bronze badges 3
  • if( coordinates.indexOf(searchFor) != -1) // exists – madhairsilence Commented Jun 27, 2013 at 12:24
  • You'd need to iterate over the object's values in the array, as they are two separate objects. Right now, you're looking for another object that just happens to have the same values, which is why it's returning -1. – Qantas 94 Heavy Commented Jun 27, 2013 at 12:25
  • are you free to use external library like underscore.js ? – Parthik Gosar Commented Jun 27, 2013 at 12:26
Add a ment  | 

6 Answers 6

Reset to default 4

This is because objects are not equal to each other - even if they have the same properties/values - unless they are the exact same instance.

What you would have to do is manually iterate through the array:

for( var i=0, l=coordinates.length, found = false; i<l; i++) {
    if( coordinates[i].x == searchFor.x && coordinates[i].y == searchFor.y) {
        found = true;
        break;
    }
}
if( found) {
    // ...
}

If you want a convenient one-liner solution, you could work with Lo-Dash.

_(coordinates).findIndex({x: 3, y: 4})
// 1

Here's a more generic approach for searching for an object within the array of objects:

Array.prototype.indexOfObj = function(o,exact){
    // make sure ining parameter is infact an object
    if (typeof o === 'object'){
        // iterate over the elements of the origin array
        for (var i = 0; i < this.length; i++){
            var match = true,
                to = this[i],
                matchedKeys = [];
            // search through o's keys and make sure they exist and
            // match the keys in the origin array
            for (var k in o){
                match &= o.hasOwnProperty(k) && to.hasOwnProperty(k);
                if (match){
                    matchedKeys.push(k);
                    match &= (k in to && to[k] == o[k]);
                }
            }
            // if we need an exact match, map it backwards as well
            // (all of o's keys == all of to's keys)
            if (match && exact){
                for (var k in to){
                    match &= to.hasOwnProperty(k);
                    // additional unmatched keys
                    if (match && matchedKeys.indexOf(k) == -1){
                        match = false;
                        break;
                    }
                }
            }
            // if it was a match, return the current key
            if (match){
                return i;
            }
        }
    }
    // default to to match found result
    return -1;
}

Then, using your example:

{x:98,y:99} non-exact = -1
{x:98,y:99} exact     = -1
{x:1}       non-exact = 0
{x:1}       exact     = -1
{x:5,y:6}   non-exact = 2
{x:5,y:6}   exact     = 2

use taffy DB, Taffy DB

var coordinates = [ {x: 1, y: 2}, {x: 3, y: 4}, {x: 5, y: 6}, {x: 7, y: 8}, {x: 9, y: 0}];
var coordinatesDB = TAFFY(coordinates);
res = coordinatesDB({x: 1, y: 2});

You could use $.grep - http://api.jquery./jQuery.grep/

coordinates = [{x: 1, y: 2}, {x: 3, y: 4}, {x: 5, y: 6}, {x: 7, y: 8}, {x: 9, y: 0}];

var query = $.grep(coordinates, function(co){ return co.x == 1 && co.y == 2; });
var hasResult = (query.length !== 0)
// query = {x: 1, y:2} - hasResult = true

As mentioned by others, you can not pare two unique objects contents by paring the objects themselves, so you have to pare their properties. You could do something like this with Array.prototype.some which is ECMA5 but can easily be shimmed.

Javascript

function indexOfCoordinates(array, object) {
    var index = -1;

    array.some(function (coordinate, arrayIndex) {
        if (coordinate.x === object.x && coordinate.y === object.y) {
            index = arrayIndex;
            return true;
        }

        return false;
    });

    return index;
}

var coordinates = [
    {x: 1, y: 2},
    {x: 3, y: 4},
    {x: 5, y: 6},
    {x: 7, y: 8},
    {x: 9, y: 0}
];

if (indexOfCoordinates(coordinates, {x: 5, y: 6}) !== -1) {
    console.log("found");
}

if (indexOfCoordinates(coordinates, {x: 9, y: 1}) === -1) {
    console.log("not found");
}

On jsfiddle

Or as you suggested, you only want true or false then you can further simplify.

Javascript

function hasCoordinate(array, object) {
    return array.some(function (coordinate) {
        return coordinate.x === object.x && coordinate.y === object.y;
    });
}

var coordinates = [
    {x: 1, y: 2},
    {x: 3, y: 4},
    {x: 5, y: 6},
    {x: 7, y: 8},
    {x: 9, y: 0}
];

if (hasCoordinate(coordinates, {x: 1, y: 2})) {
    console.log("found");
}

if (!hasCoordinate(coordinates, {x: 9, y: 1})) {
    console.log("not found");
}

On jsfiddle

This could be further generalised using ECMA5 methods Object.keys and Array.prototype.map, should you for example, change the references x and y to a and b, or extend your coordinates to include z. Now your function would still work without need of alteration.

Javascript

function hasCoordinate(array, object) {
    var objectKeys = Object.keys(object).sort(),
        objectValues = objectKeys.map(function (value) {
            return object[value];
        });

    return array.some(function (coordinate) {
        var coordinateKeys = Object.keys(coordinate).sort(),
            coordinateValues = coordinateKeys.map(function (value) {
                return coordinate[value];
            });

        return coordinateKeys.toString() === objectKeys.toString() && coordinateValues.toString() === objectValues.toString();
    });
}

var coordinates = [
    {x: 1, y: 2},
    {x: 3, y: 4},
    {x: 5, y: 6},
    {x: 7, y: 8},
    {x: 9, y: 0}
];

if (hasCoordinate(coordinates, {x: 1, y: 2})) {
    console.log("found");
}

if (!hasCoordinate(coordinates, {x: 9, y: 1})) {
    console.log("not found");
}

On jsfiddle

Of course you could continue further along the generic route, and even introduce recursion.

发布评论

评论列表(0)

  1. 暂无评论