2010-05-11 5 views
12

J'ai une chaîne commeLa meilleure façon de coder ce, chaîne à la carte de conversion en Groovy

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

Je veux le convertir en une carte

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

Ceci est la façon actuelle que je fais il,

def map = [:] 

data.splitEachLine("&"){ 

    it.each{ x -> 

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

    } 

} 

Cela fonctionne, mais y at-il un moyen plus efficace?

Répondre

21

Je ne sais pas pense que cela irait plus vite, mais il ne lui-même suggère en termes de parcimonie syntaxique:

def data = 'session=234567893egshdjchasd&userId=12345673456&timeOut=1800000' 
def result = data.split('&').inject([:]) { map, token -> 
    token.split('=').with { map[it[0]] = it[1] } 
    map 
} 

Personnellement, j'aime la réponse de Don pour une meilleure lisibilité et la maintenabilité, mais selon le contexte, cela peut être approprié.

Édition: Il s'agit en fait d'un doublage reformaté.

+3

+1 pour l'utilisation de méthodes GDK (injection) et de phrases fantaisie anglaises (parcimonie syntactique) –

+2

vous pouvez changer l'injection innards à token.split ('='). avec {map << [(it [0]): it [1]]} si vous_realement_désistez la lisibilité ;-) –

+0

J'ai aimé cette solution - jusqu'à ce que je trouve qu'il y a une fonction "collectEntries()" qui peut être utilisée pour construire des cartes. C'est beaucoup plus lisible que le "injecter()", voir ma réponse ci-dessous. –

11

Je ne sais pas si cela est plus efficace, mais à mes yeux, il est un peu plus simple (YMMV)

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

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

J'ai écrit un script Groovy rapide et sale (peut-être tout à fait défectueux) en comparant les 3 techniques mentionnées et la méthode Dons a été la plus rapide. Il a saisi 3 chaînes de requête de différentes longueurs et chronométré combien de temps pour chaque méthode, sortie par exemple: 'Méthode 1 (ig0774) [124727794, 2236178, 4806756] total: 131770728 Méthode 2 (Don) [2546134, 1174801, 2227867] 5948802 Méthode 3 (Ted Naleid) [10447068, 1915955, 2840445] total: 15203468' Assez bon pour mes fins – Steve

5

Si vous êtes à la recherche d'expressions régulières sont efficaces, où il est:

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

println map 

impressions:

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

Si vous n'êtes pas familier avec les expressions régulières, cela peut paraître un peu étranger, mais ce n'est vraiment pas si compliqué. Il a juste deux (groupes), le premier groupe est n'importe quel caractère mais un "&" ou un "=". Le deuxième groupe est n'importe quel caractère en plus d'un "=". Les groupes de capture sont de chaque côté d'un "=".

1

Voici mon effort, initialisant et remplit la carte en une seule fois, et évite la méthode d'injection que je trouve personnellement difficile à suivre: -

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 
} 
1

Après quelques recherches, « collectEntries() "est la chose magique à utiliser, elle crée un élément de carte. Travaillez comme "collect()" qui crée une liste.Donc, étant donné

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

le one-liner est

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

qui crée

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

Selon la façon dont vous voulez gérer les cas "a3" et "a4 =" vous pouvez également utiliser une version légèrement plus courte

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

et puis vous obtenez ceci:

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