नेस्टेड एसोस-लिस्ट में मूल्यों को पुनः प्राप्त करने का सबसे अच्छा तरीका है?


11

मान लीजिए कि मुझे इस तरह एक एशोक-लिस्ट मिली है:

(setq x '((foo . ((bar . "llama")
                  (baz . "monkey")))))

और मुझे मूल्य चाहिए bar। मे यह कर सकती हु:

(assoc-default 'bar (assoc-default 'foo x))

लेकिन जो मैं वास्तव में चाहूंगा वह ऐसा है जो कई कुंजियों को स्वीकार करता है, जैसे

(assoc-multi-key 'foo 'bar x)

क्या ऐसा कुछ मौजूद है, शायद एक पैकेज में कहीं? मुझे यकीन है कि मैं इसे लिख सकता हूं, लेकिन मुझे लगता है कि मेरा Google-फू अभी असफल हो रहा है और मैं इसे नहीं पा सकता हूं।


FWIW, मुझे इस पृष्ठ पर कोई भी नेस्टेड alists नहीं दिखता है। मैं केवल साधारण, अनावश्यक अल्स्टेड देखता हूं। और यह स्पष्ट नहीं है कि आप किस व्यवहार की तलाश कर रहे हैं। आप के व्यवहार के बारे में कुछ नहीं कहते हैं assoc-multi-key। संभवतः यह अपने पहले दो तर्कों के लिए दोनों के लिए मैच की तलाश में है, लेकिन यह वास्तव में वह सब है जो आप कह सकते हैं, जो आप कह सकते हैं। और यह स्पष्ट रूप से दो से अधिक कुंजियों को स्वीकार नहीं कर सकता है, क्योंकि अलिस्ट तर्क (संभवतः x) अंतिम एक है, न कि पहला - जो बताता है कि यह सामान्य रूप से बहुत उपयोगी नहीं है। वास्तव में यह निर्दिष्ट करने का प्रयास करें कि आप क्या खोज रहे हैं।
Drew

मुझे setqउदाहरण में भ्रमित करने वाले फॉर्म का मूल स्वरूपण भी मिला , इसलिए मैंने इसे एडो-सूचियों के लिए सामान्य डॉट-नोटेशन का उपयोग करने के लिए संपादित किया।
पेपरिका

आह अच्छा। तो एलिस्ट के दो स्तर होते हैं। प्रश्न अभी भी स्पष्ट नहीं है - assoc-multi-keyअनिर्दिष्ट है।
Drew

1
आकर्षित: मुद्दा assoc-multi-keyयह है कि पहली सूची को कुंजी-सूची में देखना है। यह एक नई assoc- सूची को हल करना चाहिए जिसमें हम अगली कुंजी को देखते हैं। इत्यादि। मूल रूप से नेस्टेड एशोक-लिस्ट से बाहर मूल्यों को खोदने के लिए एक छोटा-सा हाथ।
अबिंघम

2
@ मलबारबा शायद आप भी उल्लेख कर सकते let-alistहैं? जैसे (let-alist '((foo . ((bar . "llama") (baz . "monkey")))) .foo.bar)लौटेगा "llama"। मुझे लगता है let-alistकि सवाल पूछे जाने के बाद आपने लिखा था, लेकिन यह सवाल की भावना में है और बहुत ही ध्यान देने योग्य आईएमओ है!
यंगफ्रॉग

जवाबों:


15

यहां एक विकल्प है जो सटीक सिंटैक्स लेता है जो आपने सामान्य तरीके से पूछा था, और समझने में काफी सरल है। अंतर केवल इतना है कि ALISTपैरामीटर को पहले आने की आवश्यकता है (आप इसे अंतिम आने के लिए अनुकूलित कर सकते हैं, यदि यह आपके लिए महत्वपूर्ण है)।

(defun assoc-recursive (alist &rest keys)
  "Recursively find KEYs in ALIST."
  (while keys
    (setq alist (cdr (assoc (pop keys) alist))))
  alist)

तब आप इसे कॉल कर सकते हैं:

(assoc-recursive x 'foo 'bar)

2
यह कमोबेश ऐसा ही है जैसा मैंने पकाया था। मैं थोड़ा हैरान हूं कि यह डैश या कुछ जैसे कुछ स्थापित लाइब्रेरी का हिस्सा नहीं है। यह उदाहरण के लिए json डेटा के साथ काम करते समय हर समय आने लगता है।
अबिंघम

2

यहाँ एक और अधिक सामान्य समाधान है:

(defun assoc-multi-key (path nested-alist)
   "Find element in nested alist by path."
   (if (equal nested-alist nil)
       (error "cannot lookup in empty list"))
   (let ((key (car path))
         (remainder (cdr path)))
     (if (equal remainder nil)
         (assoc key nested-alist)
       (assoc-multi-key remainder (assoc key nested-alist)))))

यह चाबियों का कोई भी "रास्ता" ले सकता है। यह वापस आ जाएगी(bar . "llama")

(assoc-multi-key '(foo bar)
    '((foo (bar . "llama") (baz . "monkey"))))

जबकि यह वापस आ जाएगा (baz . "monkey"):

(assoc-multi-key '(foo bar baz)
    '((foo (bar (bozo . "llama") (baz . "monkey")))))

3
इस उत्तर के लिए मेरा पहला डाउनवोट मिला। कोई मुझे बताने को तैयार क्यों?
रेकैडो

1
मैं आपके कोड के काम करने (1) के बाद से डाउनवोट से असहमत हूं। मेरी अटकलें हैं कि @ मालाबार का उत्तर स्पष्ट रूप से प्रस्ताव पर अन्य उत्तरों की तुलना में अधिक सामान्य / सुरुचिपूर्ण है, और इसलिए अन्य उत्तरों को अस्वीकार कर दिया गया है क्योंकि वे काम नहीं करते हैं, लेकिन क्योंकि वे सबसे अच्छे नहीं हैं। (किया जा रहा है कहा कि, मैं विकल्प "सबसे अच्छा वोट दें" के बजाय "सबसे अच्छा वोट दें और दूसरों downvote" विकल्प पसंद करते हैं।)
दान

1
इन दो प्रश्नों को अस्वीकार कर दिया गया था क्योंकि यहाँ एक व्यक्ति है जो यह नहीं समझता है कि कैसे काम करता है (और एक टिप्पणी छोड़ने के लिए इंटरफ़ेस के अनुरोध की अवहेलना करता है)। यह दुर्भाग्यपूर्ण है, लेकिन सबसे अच्छा हम सभी कर सकते हैं।
मालाबार 12

0

यहां एक सरल कार्य है जो एक मुल के साथ काम करता है जो एक अन्य मुल्क के अंदर घोंसला करता है:

(defun assoc2 (outer inner alist)
  "`assoc', but for an assoc list inside an assoc list."
  (assoc inner (assoc outer alist)))

(setq alist2 '((puppies (tail . "waggly") (ears . "floppy"))
               (kitties (paws . "fuzzy")  (coat . "sleek"))))

(assoc2 'kitties 'coat alist2)       ;; => (coat . "sleek")
(cdr (assoc2 'kitties 'coat alist2)) ;; => "sleek"

3
कृपया लोग, जब आप वोट डालते हैं, तो एक टिप्पणी छोड़ दें।
मलाबारबा

1
जिसने भी अपमानित किया: मैं नाराज नहीं हूं, लेकिन मैं उत्सुक हूं कि क्यों। @ मालाबार: अब "डाउनवोट + टिप्पणी" पर मानदंडों पर एक मेटा थ्रेड है ? ; मैं आपके ले जाने के लिए उत्सुक हूँ।
दान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.