简体   繁体   English

JavaScript-在对象数组中的对象数组中查找对象

[英]JavaScript - Find an object among an array of objects, inside an array of objects

I'm using Vue, lodash, etc. 我正在使用Vue,lodash等

{
  "street": {
    "id": "1",
    "streetName": "test",
    "buildings": [
      {
        "id": "1",
        "buildingName": "test"
      }
    ]
  }
}

I have a setup similar to this. 我有一个与此类似的设置。 This is a singular object, I basically have an array of these. 这是一个单一的对象,我基本上有一个这样的数组。

All I get is a building.id value. 我得到的只是一个building.id值。

From it, I need to be able to find the building it belongs to, and there isn't any direct list of buildings for me to access. 从中,我需要能够找到它所属的建筑物,并且没有可供我访问的建筑物的直接列表。

Currently 目前

I'm using a nested loop to loop through each site until I find the one that has a building with that id. 我正在使用嵌套循环遍历每个站点,直到找到具有该ID的建筑物的站点为止。 I don't know if I'm doing it correctly, it doesn't feel correct. 我不知道我做的是否正确,感觉不正确。

for(var i = 0; i < streets.length; i++){
    for(var x = 0; x < streets[i].buildings.length;x++){
        if(streets[i].buildings[x].id == '2aec6bed-8cdd-4043-9041-3db4681c6d08'){   

        }
    }
}

Any tips? 有小费吗? Thanks. 谢谢。

You can use a combination of filter and some methods, like this: 您可以结合使用filtersome方法,例如:

var result = streets.filter(function(s) {
  return s.street.buildings.some(function(b) {
    return b.id === searchedId;
  });
});
  • Using .some() method will return true if any building of the iterated buildings has the searchedId . 使用.some()方法将返回true ,如果任何building迭代的buildingssearchedId
  • Using .filter() will filter the streets array to return only street object where the call of some() method on its buildings will return true , in other words which meets the condition of having an id equal to searchedId . 使用.filter()将过滤streets阵列仅返回street对象,其中的呼叫some()在它的方法buildings将返回true ,在满足具有的条件换句话说id等于searchedId

Demo: 演示:

 var streets = [{ "street": { "id": "1", "streetName": "test", "buildings": [{ "id": "1", "buildingName": "test" }] } }, { "street": { "id": "1", "streetName": "test", "buildings": [{ "id": '2aec6bed-8cdd-4043-9041-3db4681c6d08', "buildingName": "test" }] } }]; var searchedId = '2aec6bed-8cdd-4043-9041-3db4681c6d08'; var result = streets.filter(function(s) { return s.street.buildings.some(function(b) { return b.id === searchedId; }); }); console.log(result); 

If you're trying to get all the buildings in all streets by a buildingId , this solves the problem: 如果您尝试通过buildingId获取所有街道上的所有buildingId ,则可以解决此问题:

streetsList.map(streetItem => streetItem.street.buildings.find(building => building.id === searchedBuildingId)).filter(v => v);

.filter(v => v) is for filtering out falsy values since we want a clean result here. .filter(v => v)用于滤除虚假值,因为我们希望在此处获得干净的结果。

If there can be more than a single building in a street with the same id , then use .some instead of .find in the example. 如果有可以比用相同的街道一个单一的建筑更id ,然后使用.some代替.find的例子。

Presumably you have a streets object that contains street objects, like: 假设您有一个包含街道对象,如街道对象:

var streets = [
  street :{ ...  },
  street :{ ...  },
  ...
];

So you need to step into each street and iterate over the buildings. 因此,您需要走进每条街道并遍历建筑物。 A for loop should be fairly efficient since it can return as soon as it finds the building. for循环应该相当有效,因为它一旦找到建筑物便可以返回。 I don't think any of the built-in looping methods will do that. 我不认为任何内置的循环方法都可以做到这一点。

The code in the OP won't work, as streets[i].buildings must be streets[i].streets.buildings and if(streets[i].buildings[x].id must be if(streets[i].street.buildings[x].id . OP中的代码将不起作用,因为streets[i].buildings必须是streets[i].buildings streets[i].streets.buildingsif(streets[i].buildings[x].id必须是if(streets[i].street.buildings[x].id

Below is a working for loop version, there's also a version using recent Array methods which are very much slower even on a very small dataset. 下面是一个适用于循环的版本,还有一个使用最近的Array方法的版本,即使在非常小的数据集上,它也非常慢。 According to jsperf , the for loop version is about 100 times faster in Safari, 10 times faster in Firefox and 50 times faster in Chrome. 根据jsperf的说法for循环版本在Safari中快大约100倍,在Firefox中快10倍,在Chrome中快50倍。

I also think the for loop code is much more readable and therefore maintainable. 我也认为for循环代码更具可读性,因此可以维护。

 var streets = [{ "street": { "id": "1", "streetName": "test", "buildings": [{ "id": "1", "buildingName": "test" }, { "id": "2", "buildingName": "test" }] } }, { "street": { "id": "2", "streetName": "test", "buildings": [{ "id": "3", "buildingName": "test" }] } } ]; function getBldById(data, id) { for (var i=0, iLen=streets.length; i<iLen; i++) { var street = streets[i].street; for (var j=0, jLen=street.buildings.length; j<jLen; j++) { if (street.buildings[j].id == id) { return street.buildings[j]; } } } return null; } console.log(getBldById(streets, '1')); function getBldById2(data, id) { return data.map(streetObj => streetObj.street.buildings.find(building => building.id === id) ).filter(v => v)[0]; } console.log(getBldById2(streets, '1')); 

You might be missing street property, right? 您可能缺少street财产,对吗? I mean it should be: streets[i].street.buildings[x].id 我的意思是应该是: streets[i].street.buildings[x].id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM