【问题标题】:Check if an object with index is in array检查具有索引的对象是否在数组中
【发布时间】:2014-12-09 21:52:35
【问题描述】:
$.each(constructions, function(i,v) { 
if ($.inArray(v.name, map[ii].buildings) == -1) {//stuff}
};

constructions 是一个对象数组,每个对象都有一个唯一的名称。 map[ii].buildings 是一个包含其中一些对象的数组。我想迭代constructions中的每个对象,检查它的name参数是否出现在map[ii].buildings的对象中。

如果map[ii].buildings 数组中的每个元素只是对象名称的文本字符串,则上述代码有效,但如果该元素是整个对象,则无效.. 关闭,但没有骰子>。

【问题讨论】:

  • $.grep() 会比 $.inArray() 更适合您吗?您是在尝试检查建筑物的唯一对象 ID,还是实际上在两个不同的数组中有相同的对象?
  • @nothingisnecessary 原本是同一个对象,但是建筑物中对象的其他值发生了变化,所以很快就会变得不同,但总是同名。

标签: javascript jquery arrays object each


【解决方案1】:

尝试使用$.grep() 而不是$.inArray();你可以指定一个函数来为你做过滤。

检查$.grep()返回的数组是否有length == 0而不是检查-1

简单示例:(如果您发布“构造”对象的代码/示例会更容易)

    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>

示例 jsFiddle:http://jsfiddle.net/eLeuy9eg/3/

【讨论】:

  • 这看起来不错...但我应该更清楚一点,我怎样才能让 foundBuildings 实际上成为不在建筑物中的结构中的对象?在上下文中,游戏会检查每个建筑物是否存在于数组中,如果不存在,则会列出它们。
  • 我认为您只需将true 作为第三个参数传递给$.grep(),这将反转结果。有关 grep 的信息,请参阅 jQuery 文档:api.jquery.com/jquery.grep。你可能想重写循环结构。
  • 似乎不起作用,我对您的代码所做的编辑在这里jsfiddle.net/eLeuy9eg/2 - 感觉很接近>。
  • 更新了代码和小提琴链接,现在就试试吧。基本上检查length == 0 是否有不在constructions 中的项目,或length &gt; 0 是否有在constructions 中的项目。刚刚意识到应该可能将变量名更改为notFoundBuildings ;)
  • 没问题,在constructions 中找到与buildings 相对补集的只是你的标准集差运算。
【解决方案2】:

执行此操作的非 jQuery 方法是使用 filter。像这样的:

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

您甚至可以向数组原型添加一个新方法。有了这个,您可以使用简单的数组,或者如果您传入一个键,则可以使用对象数组。请注意,在此示例中,我已将 mapfilter 替换为执行相同功能但速度更快的循环(请参阅 cmets):

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

【讨论】:

  • 是的,Array.filter() 是个好东西。第二个示例在没有传递任何键时运行正常,但速度稍慢(jsperf.com/setsubtraction)。为什么要为对象的键创建额外的数组?由于这些函数返回的是字符串数组而不是对象数组,因此调用者需要从它的键中查找对象,对吧?
  • @nothingisnecessary 感谢您的回复。那很有意思。如果我去掉filtermap,用简单的循环替换,上面提到的原型替换方法comes out faster than grep
猜你喜欢
  • 1970-01-01
  • 2017-11-19
  • 2015-12-23
  • 2013-07-03
  • 2019-03-31
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 2021-12-10
相关资源
最近更新 更多