将键/值注入HashMap

时间:2018-08-06 17:14:00

标签: groovy

我正在尝试生成HashMap对象,该对象具有从解析的文本输入中设置的属性和值。在简单分配的情况下可以正常工作,但希望使其更聪明并使用注入。

apt_install_from_file() {

    declare -r FILE_PATH="$1" # packages
    regex["deb"]='deb "(.*)" \[args: "(.*)", "(.*)", "(.*)"\]'

    if [ -e "$FILE_PATH" ]; then
       cat < "$FILE_PATH" | while read -r LINE; do
          if [[ $LINE =~ ${regex[deb]} ]]; then
              # ...
         fi
       done
   fi
}

产生预期的输出:

def result = new HashMap();
def buildLog = """
    BuildDir: 
    MSBuildProjectFile:test.csproj
    TargetName: test
    Compile: 
    Reference: 
""".trim().readLines()*.trim()

buildLog.each { 
    def (k,v) = it.tokenize(':')
    result."${k.trim()}"=v?.trim()
}

println "\nResult:\n${result.collect { k,v -> "\t$k='$v'\n" }.join()}"

用注入替换.each {}闭包的内部之后:

Result:
    Reference='null'
    MSBuildProjectFile='test.csproj'
    BuildDir='null'
    TargetName='test'
    Compile='null'

生成的结果缺少未设置的值

it.tokenize(':').inject({ key, value -> result."${key}" = value?.trim()})

我做错了什么,尝试使用inject(“”,{...}),但似乎将may键推入了值。

1 个答案:

答案 0 :(得分:2)

inject基本上是 reduce 。约简函数采用两个参数,即上一次迭代的结果或初始值(例如累加器)以及序列中的下一个值。这样就可以了,但是由于您只期望一个序列值,所以它只会使代码复杂。

我在这里确实看到了collectEntries的一个很好的用途,因为它允许您使用小的键/值映射或两个元素的列表来创建Map。而后者有:

result = buildLog.collectEntries {
    it.split(":",2)*.trim()
}

应该为您的代码而不是buildLog.each

工作