2013-01-07 9 views
31

मैं किसी दिए गए मानचित्र में एक विशिष्ट कुंजी खोजना चाहता हूं। यदि कुंजी पाई जाती है, तो मैं मानचित्र से उस कुंजी का मान प्राप्त करना चाहता हूं।groovy: मानचित्र में एक कुंजी खोजें और उसका मूल्य

यह मैं अब तक क्या कामयाब रहे है:

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

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

if(x) 
    println x.value 

यह काम करता है, उत्पादन "पनीर" के रूप में उम्मीद है। बढ़िया है, लेकिन मैं अंत में x.value नहीं करना चाहता, और मैं if(x) नहीं करना चाहता हूं। मैं चाहता हूं कि x किसी भी तरह से मूल्य को सीधे रखें।

मैं नहीं इस तरह एक्स में सीधे मूल्य प्राप्त कर सकते हैं:

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

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

println x 

क्योंकि खोज बंद इस मामले में शून्य है, यह एक नल पॉइंटर एक्सेप्शन का परिणाम है। बेशक, ऊपर कोड स्निपेट काम करता है जब it.key == "likes", लेकिन मुझे यकीन नहीं है कि मुझे हमेशा मानचित्र में लक्ष्य कुंजी मिल जाएगी।

क्या एक "groovier" और सुरक्षित एक नक्शे पर यह करने के लिए तरीका है:

  • चेक यदि कोई नक्शा किसी कुंजी,
  • और इसलिए यदि है, इस कुंजी
  • का मूल्य प्राप्त

उत्तर

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 

?. चेक और ग्रूवी में एक अपवाद बनाने नहीं करता है। यदि कुंजी मौजूद नहीं है, तो परिणाम org.codehaus.groovy.runtime.NullObject होगा।

+0

बहुत बढ़िया। यह मेरे द्वारा चुने गए मूल उत्तर की तुलना में भी गड़बड़ है और जो मैं ढूंढ रहा था उससे बेहतर फिट बैठता है। यह चिह्नित करना जवाब है। धन्यवाद। – noumenon

+3

बंद करने का उपयोग करना बहुत महंगा है। बेहतर उपयोग 'def x = mymap.get ("पसंद")? मूल्य' वहाँ, वह अधिक कुशल है –

46

मानचित्र का उपयोग करने का पूरा बिंदु प्रत्यक्ष पहुंच है। आप निश्चित रूप से पता है कि एक नक्शे में मूल्य Groovy- false कभी नहीं होगा, तो आप ऐसा कर सकते हैं:

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

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

हालांकि, अगर मूल्य संभावित Groovy- false हो सकता है, आप का उपयोग करना चाहिए:

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

सबसे आसान समाधान है, हालांकि, अगर आप जानते हैं मूल्य Groovy- false होने के लिए (या आपको लगता है कि उपेक्षा कर सकते हैं) नहीं जा रहा है, और एक डिफ़ॉल्ट मान चाहते हैं, इस तरह है:

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

इन तीनों समाधानों में से आपके समाधान आपके उदाहरणों की तुलना में काफी तेज़ हैं, क्योंकि वे पूरे मानचित्र को कुंजी के लिए स्कैन नहीं करते हैं। वे HashMap (या LinkedHashMap) डिज़ाइन का लाभ उठाते हैं जो प्रत्यक्ष कुंजी को लगभग तात्कालिक बनाता है।

+1

धन्यवाद। मैं पूरी तरह से बिंदु खो रहा था। – noumenon

+1

यदि आप डिफ़ॉल्ट मान चाहते हैं, तो आप मानचित्र को 'def map = [:] के साथ परिभाषित कर सकते हैं। WithDefault {"default"} '। फिर आपको डिफ़ॉल्ट मान के लिए एल्विस ऑपरेटर का उपयोग करने की आवश्यकता नहीं है। बेशक, यह मानचित्र को भी अपडेट करेगा, इसलिए यदि आप इसे नहीं चाहते हैं, तो एल्विस आपका तरीका है। – fish

+0

कुंजी को डबल कोट्स के साथ भी उद्धृत किया जा सकता है, उदाहरण के लिए \t \t डीफ़ हेडर = ["सामग्री-प्रकार": "एप्लिकेशन/जेसन"] – webjockey

0

आपको नल पॉइंटर अपवाद मिलने का कारण यह है क्योंकि आपके दूसरे उदाहरण में कोई भी पसंद नहीं है ZZZ। प्रयास करें: अशक्त के लिए

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

जैसा कि सवाल में बताया गया है, मैं यह सुनिश्चित नहीं कर सकता कि कुंजी हमेशा में रहेगी मानचित्र, इसलिए मैं एक ऐसा तरीका चाहता था जो सुरक्षित रूप से काम करेगा (अपवादों के बिना) भले ही कुंजी मानचित्र में थी या नहीं। – noumenon

1

सामान्यतः, यह आपके मानचित्र में क्या निर्भर करता है इस पर निर्भर करता है। यदि इसमें शून्य मान हैं, तो चीजें मुश्किल हो सकती हैं और containsKey(key) या get(key, default) तत्व का पता लगाने के लिए वास्तव में मौजूद होना चाहिए। कई मामलों में कोड आसान हो आप एक डिफ़ॉल्ट मान परिभाषित कर सकते हैं कर सकते हैं:

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

भी ध्यान रखें कि containsKey() या get() को बंद करने की स्थापना तत्व mymap.find{ it.key == "likes" } जाँच करने के लिए की तुलना में बहुत तेजी से कर रहे हैं।बंद करने का उपयोग केवल तभी समझ में आता है जब आप वास्तव में वहां कुछ और जटिल करते हैं। आप उदा। ऐसा करते हैं:

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

या स्पष्ट मानकों के साथ:

mymap.find{ key,value -> 
    (key != "likes") return false 
    println "x value: ${value}" 
    return true // stop searching 
} 
संबंधित मुद्दे