bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Provide ability to create object from array

Open alex-frankel opened this issue 4 years ago • 2 comments

Discussed in https://github.com/Azure/bicep/discussions/4093

Originally posted by miqm August 20, 2021 Question - is it possible in ARM runtime to create an object (in fact I'd like to have a key-vault map) from an array?

I'm thinking of having a module where I can pass a list of unique names and as an output get an object where to that name will be added the resourceId of created resource, so I can use concrete resourceId referencing by name and not an array index (less error prone).

alex-frankel avatar Aug 25 '21 19:08 alex-frankel

Support for #4691 (req for #4153) would allow for a syntax like:

  • createObject(items, keyLambda) - to create an object with keys selected by the lambda
  • createObject(items, keyLambda, valueLambda) - create an object with keys & values selected by lambdas

e.g.:

var elements = [
  {
    id: 'abc'
    name: 'foo'
  }
  {
    id: 'def'
    name: 'bar'
  }
]

var keyedById = createObject(elements, x => x.id)
// equivalent to:
// {
//   abc: {
//     id: 'abc'
//     name: 'foo'
//   }
// ...

var nameById = createObject(elements, x => x.id, x => x.name)
// equivalent to:
// {
//   abc: 'foo'
//   def: 'bar'
// }

anthony-c-martin avatar Nov 08 '21 20:11 anthony-c-martin

Note that creating a dictionary from an array can be achieved with reduce, it's just not very readable:

// equivalent to the above proposed: createObject(elements, x => x.id)
var keyedById = reduce(elements, {}, (prev, cur) => union(prev, { '${cur.id}': cur }))

// equivalent to the above proposed: createObject(elements, x => x.id, x => x.name)
var nameById = reduce(elements, {}, (prev, cur) => union(prev, { '${cur.id}': cur.name }))

anthony-c-martin avatar Aug 09 '22 02:08 anthony-c-martin

Now, we have toObject(). Should this issue be closed?

TomasMalecek avatar Mar 01 '23 21:03 TomasMalecek

@TomasMalecek thanks for reminding me. Here's the working syntax that was implemented:

var elements = [
  {
    id: 'abc'
    name: 'foo'
  }
  {
    id: 'def'
    name: 'bar'
  }
]

output keyedById object = toObject(elements, x => x.id)
/* returns the following output:
{
  "abc": {
    "id": "abc",
    "name": "foo"
  },
  "def": {
    "id": "def",
    "name": "bar"
  }
}
*/

output nameById object = toObject(elements, x => x.id, x => x.name)
/* returns the following output:
{
  "abc": "foo",
  "def": "bar"
}
*/

Public documentation: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-lambda#toobject

anthony-c-martin avatar Mar 01 '23 22:03 anthony-c-martin