对象列表,如何组合具有两个键的对象具有相同的值

时间:2020-09-25 18:26:29

标签: terraform

我正在创建一个创建IAM角色的模块。消费者将提供类似的东西

role_cross_account_config = [{
     account_ids     = ["1111112222222","333332222222"]
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = ["845666666666"]
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = ["7777788888888","6666444444444"]
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = ["555564444444"]
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = ["3333399997777"]
     external_id = null
     require_mfa = true
 },{
     account_ids     = ["64558888888","24331551111","77788644433"]
     external_id = "yesss"
     require_mfa = true
 }]

我正在尝试将external_idrequire_mfa的所有具有相同值的对象合并到所有account_ids的对象中

所以我应该得到这样的东西

new_list = [{
     account_ids     = ["1111112222222","333332222222","555564444444","64558888888","24331551111","77788644433"]
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = ["845666666666","7777788888888","6666444444444"]
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = ["3333399997777"]
     external_id = null
     require_mfa = true
 }]

我能够做到这一点,但仅对于那些require_mfaexternal_id = null具有相同值的人来说,那就是使用for循环和if else逻辑。我竭尽全力寻找解决办法,但到目前为止仍未提出任何解决方案

注意:

  • require_mfa是布尔值
  • external_id是字符串
  • external_id可以具有任何值。意味着消费者可以使用他们选择的external_id输入尽可能多的对象。我正在尝试合并所有对external_id和require_mfa共享相同值的对象。

3 个答案:

答案 0 :(得分:1)

我实际上能够找到解决方案,因此我将其发布,这样有一天可能会有益于某人。

首先,我不得不更改模块,以便它将为每个account_id接受一个对象,而不是在每个对象中都有一个account_ids的列表。像这样:

role_cross_account_config = [{
     account_ids     = "333332222222"
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = "333332222222"
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = "845666666666"
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = "7777788888888"
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = "6666444444444"
     external_id = "dsaa"
     require_mfa = false
 },{
     account_ids     = "555564444444"
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = "3333399997777"
     external_id = null
     require_mfa = true
 },{
     account_ids     = "64558888888"
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = "24331551111"
     external_id = "yesss"
     require_mfa = true
 },{
     account_ids     = "77788644433"
     external_id = "yesss"
     require_mfa = true
 }]

我使用局部变量来解决它。由于我试图按两个条件进行分组,并且其中一个条件是布尔值,因此,如果将列表分为两个不同的列表,一个用于布尔值true,一个用于布尔值false。然后,我处理每个列表,并使用"for""if"按第二个条件分组。我必须使用distinct,因为这样会导致重复很多。

NOTE:这种方法在任何编程语言中都将被视为垃圾,因为它浪费时间和资源,但这是我在Terraform中仍然可以找到的唯一方法,因为它仍然是有限的语言。我相信随着Terraform的不断发展和发展,这种事情在不久的将来会变得容易得多。

locals {
  list_no_mfa = [for s in var.role_cross_account_config : 
          {
            external_id = s.external_id
            require_mfa = s.require_mfa
            account_ids = s.account_ids
          }
        if s.require_mfa != true]

  no_mfa_same_id = distinct([for s in local.list_no_mfa : 
          {
            external_id = s.external_id
            require_mfa = s.require_mfa
            account_ids = [for i in local.list_no_mfa : i.account_ids if i.external_id == s.external_id]
          }
        ])

  list_mfa = [for s in var.role_cross_account_config : 
          {
            external_id = s.external_id
            require_mfa = s.require_mfa
            account_ids = s.account_ids
          }
        if s.require_mfa != false]

  mfa_same_id = distinct([for s in local.list_mfa : 
          {
            external_id = s.external_id
            require_mfa = s.require_mfa
            account_ids = [for i in local.list_mfa : i.account_ids if i.external_id == s.external_id]
          }
        ])

  combined_list = concat(local.no_mfa_same_id, local.mfa_same_id)
}

现在local.combined_list是期​​望的结果。

答案 1 :(得分:0)

在回答问题之前要注意的一件事,您的键/值对被写为变量,因此您实际上无法像使用对象键值对那样访问它们。因此,话虽如此,如果将那些'='转换为':',则可以执行以下操作:

new_list = [{
    account_ids: [],
  external_id: "yesss",
  require_mfa: true
},{
    account_ids: [],
  external_id: "dsaa",
  require_mfa: false
},{
    account_ids: [],
  external_id: null,
  require_mfa: false
}]

role_cross_account_config = [{
     account_ids : ["1111112222222","333332222222"],
     external_id : "yesss",
     require_mfa : true
 },{
     account_ids : ["845666666666"],
     external_id : "dsaa",
     require_mfa : false
 },{
     account_ids : ["7777788888888","6666444444444"],
     external_id : "dsaa",
     require_mfa : false
 },{
     account_ids : ["555564444444"],
     external_id : "yesss",
     require_mfa : true
 },{
     account_ids : ["3333399997777"],
     external_id : null,
     require_mfa : true
 },{
     account_ids : ["64558888888","24331551111","77788644433"],
     external_id : "yesss",
     require_mfa : true
 }]
 
  for (let i = 0; i < role_cross_account_config.length; i++) {
    if (role_cross_account_config[i]['external_id'] === 'yesss' && role_cross_account_config[i]['require_mfa'] === true) {
    for (let j = 0; j < role_cross_account_config[i]['account_ids'].length; j++) {
        new_list[0]['account_ids'].push(role_cross_account_config[i]['account_ids'][j])      
    }
  }
 }
 
 console.log(new_list)

您可以使用else添加到'if'语句中,以查找其他组合,例如“ dsaa”和“ false”,“ dsaa”和“ true”。无论您要比较哪种组合。

答案 2 :(得分:-1)

现在,我了解您需要什么,我为您找到了解决方案。您将需要创建一个函数使其正常运行。我之前提到的相同问题仍然适用,您需要使它成为真正的对象键/值对,并带有':'而不是'='。

基本上,代码遍历对象数组'role_cross ...',并将“外部id”和“ require_mfa”与数组中的所有其他对象进行比较。如果找到两者的匹配项,则将这些值存储在称为“ checkedVal”的单独数组中。函数“ alreadyChecked”在迭代是否已检查组合(例如:yess和true)之前检查“ checkedVal”,如果已检查,则移至下一个要比较的对象。

一旦通过所有检查,它将在“ new_list”数组中使用预定义键创建一个新的“对象”。这样就可以很容易地将适当的值添加到数组中新创建的对象中。如果您有任何疑问,请告诉我。

我认为应该为您解决。这是代码:

let new_list = [{}]
let checkedVal = [['init1','init2']]
let nextNewEntry = 0

role_cross_account_config = [{
     account_ids : ["1111112222222","333332222222"],
     external_id : "yesss",
     require_mfa : true
 },{
     account_ids : ["845666666666"],
     external_id : "dsaa",
     require_mfa : false
 },{
     account_ids : ["7777788888888","6666444444444"],
     external_id : "dsaa",
     require_mfa : false
 },{
     account_ids : ["555564444444"],
     external_id : "yesss",
     require_mfa : true
 },{
     account_ids : ["3333399997777"],
     external_id : null,
     require_mfa : true
 },{
     account_ids : ["64558888888","24331551111","77788644433"],
     external_id : "yesss",
     require_mfa : true
 }]
 
  function alreadyChecked(external, mfa) {
    for (k=0; k < checkedVal.length; k++) {
        
        if (checkedVal[k][0] === external && checkedVal[k][1] === mfa) {
          console.log('Already checked this combination '+external+' '+mfa)
          return true
      } else if (k === checkedVal.length -1) {
            console.log('Have not checked this yet '+external+' '+mfa)
            return false
      }
      
    }
    
  }
  
  for (let i = 0; i < role_cross_account_config.length; i++) {
    if (alreadyChecked(role_cross_account_config[i]['external_id'],role_cross_account_config[i]['require_mfa'])===false) {
    console.log('moving forward with the iterations')
    nextNewEntry++;
    checkedVal[nextNewEntry-1] = []
    checkedVal[nextNewEntry-1].push(role_cross_account_config[i]['external_id'],role_cross_account_config[i]['require_mfa'])
    new_list[nextNewEntry-1] = {
    account_ids: [],
    external_id: '',
    require_mfa: ''
    }   
        for (let j = 0; j < role_cross_account_config.length; j++) {
        
        
            if (role_cross_account_config[i]['external_id'] === role_cross_account_config[j]['external_id'] && role_cross_account_config[i]['require_mfa'] === role_cross_account_config[j]['require_mfa']) {
          
            for (let h = 0; h < role_cross_account_config[j]['account_ids'].length; h++) {
            new_list[nextNewEntry-1]['account_ids'].push(role_cross_account_config[j]['account_ids'][h]);
            new_list[nextNewEntry-1]['external_id'] = role_cross_account_config[i]['external_id'];
            new_list[nextNewEntry-1]['require_mfa'] = role_cross_account_config[i]['require_mfa'];                 
            }           
            }
            
      }
      
    }    
  }
 
 console.log(new_list)
 console.log(checkedVal)
相关问题