Groovy:如何迭代Map来创建一个新的Map,其值基于特定的条件

k4ymrczo  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(191)

我绝不是groovy的Maven,所以请不要对我持有异议。
我的JSON如下所示:

{
  "metrics": [
    {
      "name": "metric_a",
      "help": "This tracks your A stuff.",
      "type": "GAUGE",
      "labels": [
        "pool"
      ],
      "unit": "",
      "aggregates": [],
      "meta": [
        {
          "category": "CAT A",
          "deployment": "environment-a"
        }
      ],
      "additional_notes": "Some stuff (potentially)"
    },
    ...
  ]
  ...
}

我将其用作所有指标的自动文档的来源。因此,我以各种方式迭代它,以获得我需要的信息。到目前为止一切顺利,我已经完成了大部分工作。问题是,这些都需要根据部署环境进行组织。这意味着,多个指标将共享相同的部署值。
我的想法是可以创建一个Map,将部署作为键,将具有匹配部署的任何指标的指标名称作为值。我应该很容易组织事情的方式,他们应该是。我不知道如何做到这一点。结果是所有的指标名称添加,这是预期的,因为我没有做任何事情来过滤掉他们。我认为groupBy在这里是有意义的,但我不知道如何有效地使用它,坦率地说,我不确定它是否能自己解决我的问题。

parentChild = [:]
children = []

metrics.each { metric ->
   def metricName = metric.name
   def depName = metric.meta.findResult{ it.deployment }
   children.add(metricName)
   parentChild.put(depName, children)
}

创建一个新Map的最佳方法是什么,其中每个键的值都基于特定的条件?
编辑:所需的结果是,结果Map中的每个关键字都是所有度量中唯一的部署值(作为字符串)。每个值都是包含该部署的每个度量的名称(作为数组)。

[environment-a:
   [metric_a,metric_b,metric_c,...], 
environment-b:
   [metric_d,metric_e,metric_f,...]
...]
os8fio9y

os8fio9y1#

我将使用withDefault()的组合,用一个新的TreeSet示例(排序后的无重复集)和标准inject()预填充每个Map条目值。
我将示例数据减少到最低限度,并添加了一些新节点:

import groovy.json.*

String input = '''\
{
  "metrics": [
    {
      "name": "metric_a",
      "meta": [
        {
          "deployment": "environment-a"
        }
      ]
    },
    {
      "name": "metric_b",
      "meta": [
        {
          "deployment": "environment-a"
        }
      ]
    },
    {
      "name": "metric_c",
      "meta": [
        {
          "deployment": "environment-a"
        },
        {
          "deployment": "environment-b"
        }
      ]
    },
    {
      "name": "metric_d",
      "meta": [
        {
          "deployment": "environment-b"
        }
      ]
    }   
  ]
}'''

def json = new JsonSlurper().parseText input

def groupedByDeployment = json.metrics.inject( [:].withDefault{ new TreeSet() } ){ res, metric ->
  metric.meta.each{ res[ it.deployment ] << metric.name }
  res
}

assert groupedByDeployment.toString() == '[environment-a:[metric_a, metric_b, metric_c], environment-b:[metric_c, metric_d]]'

如果您的metrics.meta数组应该只有一个值,您可以通过替换以下行来简化代码:

metric.meta.each{ res[ it.deployment ] << metric.name }

res[ metric.meta.first().deployment ] << metric.name

相关问题