1

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?

3
  • if( coordinates.indexOf(searchFor) != -1) // exists 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. Commented Jun 27, 2013 at 12:25
  • are you free to use external library like underscore.js ? Commented Jun 27, 2013 at 12:26

6 Answers 6

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) {
    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

@limelights no, inArray also looks for object equality
2

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

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

Comments

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 incoming 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

2 Comments

You'd need you switch from for (var k in o) to $.each() or at least include a if (o.hasOwnProperty(k)) ... check.
@Tomalak: Oh, oops--Still working on my coffee. Thanks for the heads up. ;-)
0

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});

Comments

0

You could use $.grep - http://api.jquery.com/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

Comments

0

As mentioned by others, you can not compare two unique objects contents by comparing the objects themselves, so you have to compare 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.

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.