AlwaysNeedingHelp
AlwaysNeedingHelp

Reputation: 1945

Check if an object with index is in array

$.each(constructions, function(i,v) { 
if ($.inArray(v.name, map[ii].buildings) == -1) {//stuff}
};

Where constructions is an array of objects, each with a unique name. map[ii].buildings is an array containing some of these objects. I want to iterate each object in constructions, checking if its name parameter appears in the objects of map[ii].buildings.

The above code works if the each element in the map[ii].buildings array is just the text string of the object name, but not if the element is the entire object.. close, but no dice >.<

Upvotes: 1

Views: 109

Answers (2)

nothingisnecessary
nothingisnecessary

Reputation: 6223

Try using $.grep() instead of $.inArray(); you can specify a function to do the filtering for you.

Instead of checking for -1, you check whether the array that $.grep() returns has length == 0

Simple example: (would be easier if you posted the code / example of what "constructions" objects look like)

    var constructions = [{
        Name: "Mess hall",
        SqFt: 5000
    }, {
        Name: "Infirmary",
        SqFt: 2000
    }, {
        Name: "Bungalow",
        SqFt: 2000
    }, {
        Name: "HQ",
        SqFt: 2000
    }];
    
    var buildings = [{
        Name: "Infirmary",
        SqFt: 2000
    }, {
        Name: "HQ",
        SqFt: 2000
    }];
    
    // found buildings will be list of items in "constructions" that is not in "buildings"
    var foundBuildings = $.grep(constructions, function (constructionsItem) {
        return $.grep(buildings, function (buildingsItem) {
            return buildingsItem.Name === constructionsItem.Name
        }).length == 0; // == 0 means "not in", and > 0 means "in"
    });
    
    // this just renders the results all pretty for ya
    $.each(foundBuildings, function (idx, item) {
        $("#output").append("<div>" + item.Name + "</div>");
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='output'></div>

Example jsFiddle: http://jsfiddle.net/eLeuy9eg/3/

Upvotes: 2

Andy
Andy

Reputation: 63524

The non-jQuery way of doing this would be to use filter. Something like this:

// pass in an array and the key for which you want values
// it returns an array of those values
function getValues(arr, key) {
  return arr.map(function (el) { return el[key]; });
}

function notFoundIn(arr, arr2) {

  // grab the names of the buildings
  var buildings = getValues(arr2, 'name');

  // grab the names from the construction objects and filter
  // those that are not in the building array
  return getValues(arr, 'name').filter(function (el) {
    return buildings.indexOf(el) === -1;
  });
}

notFoundIn(constructions, buildings); // eg [ "one", "three" ]

DEMO

You could even add a new method to the array prototype. With this one you can use either simple arrays, or arrays of objects if you pass in a key. Note in this example I've replaced map and filter with loops that perform the same functions, but faster (see comments):

function getValues(arr, key) {
  var out = [];
  for (var i = 0, l = arr.length; i < l; i++) {
    out.push(arr[i][key]);
  }
  return out;
}

if (!Array.prototype.notFoundIn) {
  Array.prototype.notFoundIn = function (inThisArray, key) {
    var thisArr = key ? getValues(this, key) : this;
    var arrIn = key ? getValues(inThisArray, key) : inThisArray;
    var out = [];
    for (var i = 0, l = thisArr.length; i < l; i++) {
      if (arrIn.indexOf(thisArr[i]) === -1) {
        out.push(thisArr[i]);
      }
    }
    return out;
  }
}


constructions.notFoundIn(buildings, 'name');
[1, 2, 3].notFoundIn([2]); // [1, 3]

DEMO

Upvotes: 0

Related Questions