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
6 Answers
Reset to default 4This 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.