Лучший способ закодировать это, преобразовать строку в карту в Groovy
У меня есть строка вроде
def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
Я хочу преобразовать его в карту
["session", 234567893egshdjchasd]
["userId", 12345673456]
["timeout", 1800000]
Это мой текущий способ,
def map = [:]
data.splitEachLine("&"){
it.each{ x ->
def object = x.split("=")
map.put(object[0], object[1])
}
}
Это работает, но есть ли более эффективный способ?
Ответы
Ответ 1
Я не знаю, думаю, что это будет работать быстрее, но это дает о себе знать с точки зрения синтаксической экономии:
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
}
Лично мне нравится, что Дон отвечает за удобочитаемость и удобство обслуживания, но в зависимости от контекста это может быть уместно.
Редактировать: это на самом деле переформатированный однострочник.
Ответ 2
Я не знаю, эффективнее ли это, но для моих глаз это немного проще (YMMV)
def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
def map = [:]
data.split("&").each {param ->
def nameAndValue = param.split("=")
map[nameAndValue[0]] = nameAndValue[1]
}
Ответ 3
Если вы ищете эффективные, регулярные выражения находятся там, где они:
def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
def map = [:]
data.findAll(/([^&=]+)=([^&]+)/) { full, name, value -> map[name] = value }
println map
Отпечатки:
[session:234567893egshdjchasd, userId:12345673456, timeOut:1800000]
Если вы не знакомы с регулярными выражениями, это может показаться немного иностранным, но это действительно не так сложно. У него просто две (группы), первая группа - любой символ, но "&" или "=" . Вторая группа - любой символ, кроме "=" . Группы захвата находятся по обе стороны от "=" .
Ответ 4
После некоторого поиска "collectEntries()" - это волшебная вещь для использования, она создает элемент карты. Работайте так же, как "collect()", который создает список. Таким образом,
def params = "a1=b1&a2=b2&a3&a4=&a5=x=y"
однострочный
map = params.tokenize("&").collectEntries{
it.split("=",2).with{
[ (it[0]): (it.size()<2) ? null : it[1] ?: null ]
}
}
который создает
map = [a1:b1, a2:b2, a3:null, a4:null, a5:x=y]
В зависимости от того, как вы хотите обрабатывать случаи "a3" и "a4 =", вы также можете использовать немного более короткую версию
...
[ (it[0]): (it.size()<2) ? null : it[1] ]
...
а затем вы получите следующее:
map = [a1:b1, a2:b2, a3:null, a4:, a5:x=y]
Ответ 5
Если вы находитесь в контроллере grails, тогда это красиво и просто:
GrailsParameterMap map = new GrailsParameterMap(request)
http://grails.org/doc/latest/api/org/codehaus/groovy/grails/web/servlet/mvc/GrailsParameterMap.html
Ответ 6
Если вы используете Grails, лучшим способом я нахожу WebUtils функцию fromQueryString.
https://grails.github.io/grails-doc/2.0.x/api/org/codehaus/groovy/grails/web/util/WebUtils.html
Ответ 7
Здесь мое усилие, которое инициализирует и заполняет карту за один раз, и избегает метода инъекции, который мне лично трудно найти: -
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
}
Ответ 8
Я бы не советовал использовать сплит вообще.
Split создает новую строку, тогда как при создании коллекции переменных среды вам, вероятно, понадобится список карт.
Токенизируйте как на начальный разрыв (&), так и на вложенный разрыв (=). Хотя большинство интерпретаторов по-прежнему работают, некоторые могут выполнить разделение буквально, и в результате вы получите список строк, а не список карт.
def data= "test1=val1&test2=val2"
def map = [:]
map = data.tokenize("&").collectEntries {
it.tokenize("=").with {
[(it[0]):it[1]]
}
}