2013-01-07 17 views
31

Chcę znaleźć konkretny klucz na danej mapie. Jeśli klucz zostanie znaleziony, wtedy chcę uzyskać wartość tego klucza z mapy.groovy: znajdź klucz na mapie i zwróć jego wartość

To co udało mi się do tej pory:

def mymap = [name:"Gromit", likes:"cheese", id:1234] 

def x = mymap.find{ it.key == "likes" } 

if(x) 
    println x.value 

To działa, wyjście jest „ser”, jak oczekiwano. Świetnie, ale nie chcę na końcu robić x.value i nie chcę robić if(x). Chcę, aby x w sposób bezpośredni zawierał wartość.

nie mogę uzyskać wartość bezpośrednio w X tak:

def mymap = [name:"Gromit", likes:"cheese", id:1234] 

def x = mymap.find{ it.key == "likesZZZ" }.value 

println x 

Ponieważ zamknięcie znalezisko ma wartość null w tym przypadku, to powoduje wyjątek pustego wskaźnika. Oczywiście powyższy fragment kodu działa, gdy it.key == "likes", ale nie jestem pewien, czy zawsze znajdę klucz docelowy na mapie.

Co to jest „Groovier” i bezpieczny sposób to zrobić na mapie:

  • Sprawdź, czy mapa ma dany klucz,
  • a jeśli tak, uzyskać wartość tego klucza

Odpowiedz

10
def mymap = [name:"Gromit", id:1234] 
def x = mymap.find{ it.key == "likes" }?.value 
if(x) 
    println "x value: ${x}" 

println x.getClass().name 

?. kontrole za nieważną i nie tworzy wyjątek w Groovy. Jeśli klucz nie istnieje, wynikiem będzie org.codehaus.groovy.runtime.NullObject.

+0

Awesome. Jest to nawet bardziej zacięte niż oryginalna odpowiedź, którą wybrałem i lepiej pasuje do tego, czego szukałem. Oznaczenie to jest odpowiedź. Dzięki. – noumenon

+3

Korzystanie z zamknięcia jest bardzo drogie. Lepiej użyj 'def x = mymap.get (" lubi ")" wartość "tam, o wiele bardziej wydajną –

46

Cały punkt korzystania z aplikacji Mapy to bezpośredni dostęp. Jeśli wiesz na pewno, że wartość w mapie nie będzie Groovy- false, to można to zrobić:

def mymap = [name:"Gromit", likes:"cheese", id:1234] 
def key = "likes" 

if(mymap[key]) { 
    println mymap[key] 
} 

Jednakże, jeżeli wartość potencjalnie mogłyby być Groovy- false, należy użyć:

if(mymap.containsKey(key)) { 
    println mymap[key] 
} 

Najprostszym rozwiązaniem, chociaż, jeśli wiesz, że wartość ta nie będzie Groovy- false (lub można zignorować) i chcą wartość domyślną, to tak:

def value = mymap[key] ?: "default" 

Wszystkie te trzy rozwiązania są znacznie szybsze niż przykłady, ponieważ nie skanują całej mapy pod kątem kluczy. Korzystają z projektu HashMap (lub LinkedHashMap), który zapewnia bezpośredni dostęp do klucza prawie natychmiastowo.

+1

Dzięki. Całkowicie nie rozumiałem. – noumenon

+1

Jeśli chcesz wartości domyślne, możesz zdefiniować mapę jako 'def map = [:]. WithDefault {" Default "}'. Wtedy nie musisz używać operatora Elvisa dla wartości domyślnej. Oczywiście to również zaktualizuje mapę, więc jeśli tego nie chcesz, to Elvis jest na twojej drodze. – fish

+0

Klucz można również podawać z podwójnymi cudzysłowami, na przykład \t \t nagłówki def = ["Content-Type": "application/json"] – webjockey

0

Powód, dla którego uzyskano wyjątek wskaźnika pustego, jest taki, że w drugim przykładzie nie ma żadnego klucza do ZZZ. Spróbuj:

def mymap = [name:"Gromit", likes:"cheese", id:1234] 
def x = mymap.find{ it.key == "likes" }.value 
if(x) 
    println "x value: ${x}" 
+0

Jak stwierdzono w pytaniu, nie mogę być pewien, że klucz zawsze będzie w kluczu map, więc chciałem mieć sposób, który działałby bezpiecznie (bez wyjątków), nawet jeśli klucz był lub nie był na mapie. – noumenon

1

Zasadniczo zależy to od zawartości mapy. Jeśli ma wartości puste, rzeczy mogą być trudne i aby wykryć naprawdę istniejący element, należy użyć wartości containsKey(key) lub get(key, default). W wielu przypadkach kod może stać się prostsze można określić wartość domyślną:

def mymap = [name:"Gromit", likes:"cheese", id:1234] 
def x1 = mymap.get('likes', '[nothing specified]') 
println "x value: ${x}" } 

Należy również zauważyć, że containsKey() lub get() są znacznie szybsze niż utworzenie zamknięcie sprawdzić element mymap.find{ it.key == "likes" }.Używanie zamknięcia ma sens tylko wtedy, gdy naprawdę robisz coś bardziej skomplikowanego. Możesz np. to zrobić:

mymap.find{ // "it" is the default parameter 
    if (it.key != "likes") return false 
    println "x value: ${it.value}" 
    return true // stop searching 
} 

lub przy wyraźnych parametrów:

mymap.find{ key,value -> 
    (key != "likes") return false 
    println "x value: ${value}" 
    return true // stop searching 
} 
Powiązane problemy