Using setproduct, how can I remove items from the result?

I’m working to create a mesh of Azure VNets using VNet Peering, meaning every VNet needs to be peered to every other VNet, but not to itself.

I thought I could take a set of VNets and “setproduct” it against itself, like this:

locals {
  vnets = ["vnet-1", "vnet-2", "vnet-3"]
  vnet_peers = setproduct(local.vnets, local.vnets)
}

Unfortunately (and as I’d expect from setproduct) the result includes sets where both items are the same, as seen below:

local.vnet_peers
[
  [
    "vnet-1",
    "vnet-1",
  ],
  [
    "vnet-1",
    "vnet-2",
  ],
  [
    "vnet-1",
    "vnet-3",
  ],
  [
    "vnet-2",
    "vnet-1",
  ],
  [
    "vnet-2",
    "vnet-2",
  ],
  [
    "vnet-2",
    "vnet-3",
  ],
  [
    "vnet-3",
    "vnet-1",
  ],
  [
    "vnet-3",
    "vnet-2",
  ],
  [
    "vnet-3",
    "vnet-3",
  ],
]

My goal here is to get a result that doesn’t include sets where both items are the same. I need a result that doesn’t include items like the following:

BAD - I need a result without sets like this where both items are the same:

  [
    "vnet-1",
    "vnet-1",
  ]

GOOD - Both are different:

  [
    "vnet-1",
    "vnet-2",
  ]

Any suggestions?

Hi @JohnDelisle,

The general solution to any transformations of collections is the for expression. In this case, you can use its if clause to exclude the elements where both values are equal:

  vnet_peers = [
    for pair in setproduct(local.vnets, local.vnets) : pair
    if pair[0] != pair[1]
  ]

Thanks! I didn’t realize I could use an “if” there.

Thanks Martin! Appreciate your response.

As a new Terraform user, something I’d find incredibly helpful would be a library of design patterns for the manipulation of data structures using for_each/ for/ conditionals etc…

I’m coming from a procedural programming world, and have found this to be the most challenging aspect of working with Terraform.

I see you’re very active in the Terraform community and thought you might be interested in the feedback.

Thanks