string 最好的编码方式,字符串到 Groovy 中的映射转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2812689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:44:47  来源:igfitidea点击:

Best way to code this, string to map conversion in Groovy

stringgroovymap

提问by Daxon

I have a string like

我有一个像

def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"

I want to convert it to a map

我想把它转换成地图

 ["session", 234567893egshdjchasd]
 ["userId", 12345673456]
 ["timeout", 1800000]

This is the current way I am doing it,

这是我目前的做法,

 def map = [:]

 data.splitEachLine("&"){

   it.each{ x ->

     def object = x.split("=")
     map.put(object[0], object[1])

   }

 }

It works, but is there a more efficient way?

它有效,但有没有更有效的方法?

回答by ig0774

I don't know think this is would run any faster, but it does suggest itself in terms of syntactic parsimony:

我不知道这是否会运行得更快,但它确实在语法简约方面提出了自己的建议:

def data = 'session=234567893egshdjchasd&userId=12345673456&timeOut=1800000'
def result = data.split('&').inject([:]) { map, token -> 
    //Split at "=" and return map with trimmed values
    token.split('=').with { 
        map[it[0].trim()] = it[1].trim() 
    }
    map 
}

Personally, I like Don's answer for readability and maintainability, but depending on context, this may be appropriate.

就个人而言,我喜欢 Don 对可读性和可维护性的回答,但根据上下文,这可能是合适的。

Edit:This is actually a reformatted one-liner.

编辑:这实际上是重新格式化的单行。

回答by Dónal

I don't know if this is more efficient, but to my eyes, it's a bit simpler (YMMV)

我不知道这是否更有效,但在我看来,它更简单(YMMV)

def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
def map = [:]

data.split("&").each {param ->
    def nameAndValue = param.split("=")
    map[nameAndValue[0]] = nameAndValue[1]
}

回答by Ted Naleid

If you're looking for efficient, regular expressions are where it's at:

如果您正在寻找高效的正则表达式,它就在:

def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
def map = [:]
data.findAll(/([^&=]+)=([^&]+)/) { full, name, value ->  map[name] = value }

println map

prints:

印刷:

[session:234567893egshdjchasd, userId:12345673456, timeOut:1800000]

If you're not familiar with regular expressions, it might look a little foreign, but it's really not that complicate. It just has two (groups), the first group is any character but a "&" or a "=". The second group is any character besides a "=". The capture groups are on either side of a "=".

如果您不熟悉正则表达式,它可能看起来有点陌生,但实际上并没有那么复杂。它只有两个(组),第一组是除“&”或“=”之外的任何字符。第二组是除“=”之外的任何字符。捕获组位于“=”的两侧。

回答by Axel Heider

After some searching, "collectEntries()" is the magic thing to use, it creates a map element. Work just like "collect()" that creates a list. So given

经过一番搜索,“collectEntries()” 是一个神奇的东西,它创建了一个地图元素。就像创建列表的“collect()”一样工作。所以给出

def params = "a1=b1&a2=b2&a3&a4=&a5=x=y"

the one-liner is

单线是

map = params.tokenize("&").collectEntries{ 
          it.split("=",2).with{ 
              [ (it[0]): (it.size()<2) ? null : it[1] ?: null ] 
          }
      }

which creates

这创造了

map = [a1:b1, a2:b2, a3:null, a4:null, a5:x=y]

Depending how you want to handle the cases "a3" and "a4=" you can also use a slightly shorter version

根据您想如何处理“a3”和“a4=”的情况,您还可以使用稍短的版本

...
[ (it[0]): (it.size()<2) ? null : it[1] ] 
...

and then you get this:

然后你会得到这个:

map = [a1:b1, a2:b2, a3:null, a4:, a5:x=y]

回答by JapethMarvel

I wouldn't suggest using split at all.

我根本不建议使用 split 。

Split creates a new string, whereas when creating a collection of environment variables, you would probably want a list of maps.

Split 创建一个新字符串,而在创建环境变量集合时,您可能需要一个映射列表。

Tokenize both on the initial break (&) and on the nested break (=). While most interpreters will still work, some may run the split literally, and you'll end up with a list of strings, rather than a list of maps.

在初始中断 (&) 和嵌套中断 (=) 上标记。虽然大多数解释器仍然可以工作,但有些解释器可能会按字面意思运行拆分,并且您最终会得到一个字符串列表,而不是一个映射列表。

def data= "test1=val1&test2=val2"
def map = [:]

map = data.tokenize("&").collectEntries {
    it.tokenize("=").with {
        [(it[0]):it[1]]
    }
}

回答by gabe

If you are in a grails controller, then this is nice and simple:

如果您在 grails 控制器中,那么这很简单:

GrailsParameterMap map = new GrailsParameterMap(request)

http://grails.org/doc/latest/api/org/codehaus/groovy/grails/web/servlet/mvc/GrailsParameterMap.html

http://grails.org/doc/latest/api/org/codehaus/groovy/grails/web/servlet/mvc/GrailsParameterMap.html

回答by mcflycox

If you use Grails, the best way I find is WebUtils the function fromQueryString.

如果您使用 Grails,我发现最好的方法是 WebUtils 函数 fromQueryString。

https://grails.github.io/grails-doc/2.0.x/api/org/codehaus/groovy/grails/web/util/WebUtils.html

https://grails.github.io/grails-doc/2.0.x/api/org/codehaus/groovy/grails/web/util/WebUtils.html

回答by Dave00Galloway

Here's my effort, which initializes and fills the map in one go, and avoids the inject method which I personally find hard to follow:-

这是我的努力,它一次性初始化并填充地图,并避免了我个人觉得难以遵循的注入方法:-

    def map = data.split('&').collectEntries {
        def kvp = it.split('=').collect { string ->
            string = string.trim()
            return string
    }
    [(kvp[0]): kvp.size() > 1 ? kvp[1] ?: '' : '']
    // the null check is almost certainly overkill so you could use :-
    // [(kvp[0]): kvp.size() > 1 ? kvp[1] : '']
    // this just checks that a value was found and inserts an empty string instead of null 
}