Groovy 从文本行创建地图

Groovy create map from lines of text

我有包含在 3 个单独行中的原始数据。我想使用每条线的一部分构建一个地图记录。然后我阅读接下来的 3 行并创建下一个地图记录等等。我在地图上找到的所有 groovy 示例都显示它们是根据单行数据创建的,或者我可能误解了这些示例。这是原始数据的样子。

snmp v2: data result = "Local1"
snmp v2: data result ip = "10.10.10.121"
snmp v2: data result gal = "899"
new
snmp v2: data result = "Local2"
snmp v2: data result ip = "192.168.10.2"
snmp v2: data result gal = "7777"
new  

我想将这些数据放入地图中。在此示例中,Local1 和 Local2 将是键,它们各有 2 个关联值。我将向您展示我最近的尝试,但这只不过是一个失败的猜测。

def data = RAW
def map = [:]
data.splitEachLine("="){
 it.each{ x ->
 map.put(it[0], it[1])

 map.each{ k, v -> println "${k}:${v}" } }}   

期望的输出是:

[ Local1 : [ ip: "10.10.10.121", gal: "899" ], 
Local2: [ ip: "192.168.10.2", gal: "7777" ] ]      

如果你想获得 dmahapatro 建议的嵌套地图,试试这个:

def map = [:]

data=data.eachLine() { line ->
  if(line.startsWith("new")) return
  tokens=line.replace("snmp v2: data","").split("=")
  tokens=tokens.collect() { it.trim().replace("result ","").replaceAll(/"/, "") }
  if(tokens[0]=="result") {
      nested=[:]
      map[tokens[1]]=nested
  }
  else
      nested[tokens[0]]=tokens[1]
}
println("map: $map")

这里我们:

  • 遍历行
  • 跳过开头为 "new" 的行
  • 从行的文本中删除 "snmp v2: data"
  • 将每一行拆分为标记,trim() 每个标记,并删除 "result " 和引号 令牌成对出现,现在看起来像:

    结果,Local1

    ip, 10.10.10.121

    加仑,899

  • next 当第一个token为"result"时,我们构建一个嵌套映射,并放置在主映射中由token[1]

    的值给定的key处
  • 否则我们使用 key=token[0] 和 value=token[1]
  • 填充嵌套映射

结果是:

map: [Local1:[ip:10.10.10.121, gal:899], Local2:[ip:192.168.10.2, gal:7777]]

编辑:修复删除引号

您可以使用在集合上定义的聚合操作从现有数据结构构建新数据结构; collect 从现有列表生成列表,collectEntries 从列表创建映射。

问题指定一个条目总是三行,然后是带有 "new" 的一行。如果我可以假设它们总是以相同的顺序排列,我可以从每行中取出最后一个词,使用 collat​​e 将每四行分组到一个子列表中,然后将每个子列表转换为一个映射条目:

lines = new File('c:/temp/testdata.txt').readLines()
mymap = lines.collect { it.tokenize()[-1] }
  .collate(4)
  .collectEntries { e-> [(e[0].replace('"', ''))) : [ip: e[1], gal: e[2]]] }

计算结果为

[Local1:[ip:"10.10.10.121", gal:"899"], Local2:[ip:"192.168.10.2", gal:"7777"]]

或者去掉第一步中的所有引号:

mymap = lines.collect { (it.tokenize()[-1]).replace('"', '') }
  .collate(4)
  .collectEntries { e-> [(e[0]) : [ip: e[1], gal: e[2]]] }

为了得到

[Local1:[ip:10.10.10.121, gal:899], Local2:[ip:192.168.10.2, gal:7777]]