Объединение массива объектов в rego

#open-policy-agent #rego

#open-policy-agent #rego

Вопрос:

Как мне объединить массив объектов в один объект в rego ?

Я знаю, как объединить два объекта, но как мне выполнить цикл по массиву объектов?

Этот пример работает, но он (очевидно) не масштабируется 😉

 
a := [{"test1": "123"}, {"test2": "456"}, {"test3": "789", "test4": "012"}]

b := {
        "my-property": object.union(object.union(a[0], a[1]), a[2])
     }
  

Ожидаемый результат:

 {
  "test1": "123", 
  "test2": "456",
  "test3": "789",
  "test4": "012"
}
  

Спасибо!
Каспер

Ответ №1:

TLDR; предполагая, что ключи объекта уникальны (как в вашем примере), вы можете просто использовать понимание:

 b := {k: v | 
    some i, k
    v := a[i][k]
}
  

Поскольку переменная i используется только один раз, вы можете заменить ее на _ , чтобы избежать необходимости придумывать имя:

 b := {k: v | 
    some k
    v := a[_][k]
}
  

Если ключи объекта не уникальны, это немного сложнее, потому что вам нужно решить, как разрешать конфликты, когда два объекта содержат один и тот же ключ с разными значениями. То, как вы решите разрешить конфликты, будет зависеть от варианта использования. Один из способов разрешить их — просто сгруппировать значения по их ключам. Например:

 # the 'test2' key appears in more than one object with a different value
a := [{"test1": "123"}, {"test2": "456"}, {"test3": "789", "test2": "012"}]
  

Чтобы сгруппировать значения по ключам, вы можете написать вложенное понимание:

 {k: vs |
    # for each key 'k'
    some k
    conflicting[_][k]

    # find all values for key 'k' and group as a set
    vs := {v | v := conflicting[_][k]}
}
  

Вывод:

 {
    "test1": [
        "123"
    ],
    "test2": [
         "012",
         "456"
    ],
    "test3": [
         "789"
    ]
}
  

Комментарии:

1. Потрясающе! Я пробовал с пониманием объекта, но часть, которую мне не хватало, была k: v -part . Еще раз спасибо!