Подтвердить что ты не робот

Лучший способ закодировать это, преобразовать строку в карту в 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])

   }

 }

Это работает, но есть ли более эффективный способ?

4b9b3361

Ответ 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]

Ответ 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]]
    }
}