迭代对象数组并过滤掉不匹配的对象

iterate over array of objects and filter out not matching

本文关键字:对象 不匹配 数组 迭代 过滤      更新时间:2023-09-26

我正在努力找出进行一些对象迭代/突变的最佳lodashy方法。我试图找到所有具有"DB"角色的服务器的"sid"。预期的结果将是一个变量,该变量具有任何sid的完整道具(tier、sidadm、sid、orasid、server),这些sid的服务器具有角色DB。

数据

var landscape = [
  {
    "tier": "production", 
    "sidadm": "ptpadm", 
    "sid": "PTP", 
    "orasid": "oraptp", 
    "servers": [
      {
        "hostname": "testep00", 
        "roles": ["DB"]
      }, 
      {
        "hostname": "testep01", 
        "roles": ["DG"]
      }, 
      {
        "hostname": "testep02", 
        "roles": ["SAPMS"]
      }, 
      {
        "hostname": "testep03", 
        "roles": ["SAPDI"]
      }, 
      {
        "hostname": "testep04", 
        "roles": ["SAPDI"]
      }, 
      {
        "hostname": "testep05", 
        "roles": ["SAPDI"]
      }, 
      {
        "hostname": "testep06", 
        "roles": ["SAPDI"]
      }
    ]
  },  
  {
    "tier": "techsandbox", 
    "sidadm": "bwzadm", 
    "sid": "BWZ", 
    "orasid": "orabwz", 
    "servers": [
      {
        "hostname": "testbw80", 
        "roles": ["DB"]
      }, 
      {
        "hostname": "testbw81", 
        "roles": ["DG"]
      }, 
      {
        "hostname": "testbw82", 
        "roles": ["SAPMS"]
      }, 
      {
        "hostname": "testbw83", 
        "roles": ["SAPDI"]
      }
    ]
  }, 
  {
    "tier": "techsandbox", 
    "sidadm": "eczadm", 
    "sid": "ECZ", 
    "orasid": "oraecz", 
    "servers": [ 
      {
        "hostname": "testec81", 
        "roles": ["DG"]
      }, 
      {
        "hostname": "testec82", 
        "roles": ["SAPDI", "SAPMS"]
      }
    ]
  }
];

到目前为止,这就是我所拥有的,有点,但不排除具有空服务器道具的SID。一定有更好的方法用洛达什写这篇文章,对吧?

// find me all SIDs with role "DB",
// should filter landscape and only return sids which have servers role=DB
// also should only contain the servers which are role=DB
var ls = _.extend({}, landscape);
_.each(ls, function (sid) {
  var servers = _.filter(sid.servers, function (server) {
    return _.contains(server.roles, 'DB');
  });
  // still need to strip out SID objects which have empty servers prop
  sid.servers = servers;
});
console.log('sids1() ::', ls);

只要一个简单的filter+some就足够了:

var result = landscape.filter(function(sid) {
  return sid.servers.some(function(server) {
    return server.roles.indexOf("DB") > -1;
  });
});

如果你喜欢的话,Lodash提供了这两种功能的实现

如果您还希望只包括具有该特定角色的服务器,则可以使用mapfilter:

var result = landscape
  .map(function(sid) {
    return Object.assign( // "clone" object
      {},
      sid,
      {
        servers: sid.servers.filter(function(server) {
          return server.roles.indexOf("DB") > -1;
        })
      }
    );
  })
  .filter(function(sid) {
    return sid.servers.length > 0;
  });

这也可以组合成单个reduce或使用简单的forEach:

var result = [];
landscape.forEach(function(sid) {
  var servers = sid.servers.filter(function(server) {
    return server.roles.indexOf("DB") > -1;
  });
  if (servers.length > 0) {
    result.push(Object.assign({}, side, {servers: servers});
  }
});