How to combine all tuples in list of maps

Hi @mikedavem1,

Looking at your “initial result” it seems to be an object with numbers as its attribute names rather than a tuple, and so I think that might be why flatten isn’t flattening all the way like you probably hoped.

With that said, the expression you shared does seem to produce a tuple and so I don’t follow how the expression you showed would return that result. That’s not super important though, because I think I can see from your example what your goal is.

I think the key here would be to use merge instead of flatten, because merge can combine multiple objects or maps together to produce an object or map, which matches your desired result.

merge is a variadic function, meaning that it takes an arbitrary number of arguments rather than a single collection argument, but we can tell Terraform to use the contents of a tuple or list to populate those arguments by using the special ... modifier after the argument, as described in Expanding Function Arguments.

locals {
  test = merge([
    for key, env in var.api_gw_jwt_list_sa : {
      for info in env : info.sa => {
        flow             = "implicit"
        authorizationUrl = ""
      }
    }
    if key == var.space
  ]...)
}

Notice here that the inner for expression uses { } braces and therefore produces an object value rather than a tuple value. The outer for expression uses [ ] and so it produces a tuple value, where the tuple elements are each objects from the inner for expression. The ... modifier after that outer expression tells Terraform to pass each element of that outer tuple as a separate argument to merge, and so merge will see this as a dynamically-chosen number of arguments that are each objects, which is the signature it expects. Its return value is therefore the merger of all of those objects.


With that said, I noticed that you’ve written the outer for expression to filter based on a specific value of key. Since there can only be one element with a particular key, it might be simpler to first look up that single element via an index expression and then work just with that object alone. For example:

locals {
  # I've written this as a "try" to give a
  # fallback to an empty tuple if the
  # given key doesn't exist, because that
  # gets a similar effect to your example.
  # However, if you expect the key to
  # always exist you could simplify this
  # further by removing the "try" call here.
  space_api_gw_jwt_list = try(var.api_gw_jwt_list_sa[var.space], [])

  test = {
    for info in local.space_api_gw_jwt_list : info.sa => {
      flow             = "implicit"
      authorizationUrl = ""
    }
  }
}

I haven’t tested the examples I’ve shown here because I don’t have your var.api_gw_jwt_list_sa to test against, so I apologize if there are typos or other errors. If you get any error messages you’re not sure about when you try this then please let me know and I’ll do my best to explain and correct what I showed above.