Built-in function for creating distinct "sets" from an array
Is your feature request related to a problem? Please describe. With variable looping soon supported, a feature that is missed in Bicep (and ARM) is a simple way of creating a distinct array /set from an array with duplicate values.
This is something that have equivalent functions in Terraform with the distinct() function:
distinct takes a list and returns a new list with any duplicate elements removed. The first occurrence of each value is retained and the relative ordering of these elements is preserved.
Describe the solution you'd like New built-in function that reduces an array into a distinct set (but still an array type - not suggesting a new type).
Simple example:
var myArray = [
'foo'
'foo'
'bar'
]
output distinctArray = distinct(myArray)
// ==> [ 'foo', 'bar' ]
A functionally equivalent method of doing this is union(myArray, myArray) but this is not very clear.
Another example:
param vmObjects array = [
{
name: 'vm1'
location: 'westeurope'
}
{
name: 'vm2'
location: 'westeurope'
}
{
name: 'vm3'
location: 'westeurope'
}
]
resource vms 'Microsoft.Compute/virtualMachines@2020-12-01' = [for vm in vmObjects: {
name: vm.name
location: vm.location
}]
var locations = [for vm in vmObjects: vm.location]
resource storage 'Microsoft.Storage/storageAccounts@2021-01-01' = [for location in distinct(locations): {
name: 'stg'
location: location
kind: 'BlobStorage'
sku:{
name: 'Standard_LRS'
tier:'Standard'
}
}]
A functionally equivalent method of doing this is use union(locations, locations) in the resource loop expression.
As a note to myself next time I look this up (or for others), this is a working method of doing this either by using lambdas or union:
param vmObjects array = [
{
name: 'vm1'
location: 'westeurope'
}
{
name: 'vm2'
location: 'northeurope'
}
{
name: 'vm3'
location: 'westeurope'
}
]
var allLocations = map(vmObjects, item => item.location)
// These are functionally equivalent on arrays
output uniqueLocationsUnion array = union(allLocations, allLocations)
output uniqueLocationsLambda array = reduce(allLocations, [], (cur, next) => union(cur,[next]))
// => [ 'westeurope', 'northeurope' ]
As a workaround, we can polyfill such a distinct() function as follows:
func distinct(arrayWithDuplicates array) array => union(arrayWithDuplicates, [])
And then use it just like you would invoke the hypothetical built-in function.
param vmObjects array = [
{
name: 'vm1'
location: 'westeurope'
}
{
name: 'vm2'
location: 'northeurope'
}
{
name: 'vm3'
location: 'westeurope'
}
]
output uniqueLocations array = distinct(map(vmObjects, item => item.location))
// => [ 'westeurope', 'northeurope' ]