एक संपत्ति सूची में एक समारोह मानचित्र?


17

प्रश्न: प्रॉपर्टी लिस्ट में किसी फंक्शन को मैप करने के लिए मुहावरेदार तरीका क्या है?

विभिन्न मैपिंग फ़ंक्शंस ( mapcarऔर परिवार) एक अनुक्रम को एक सूची में मैप करते हैं जैसे कि एक सूची। प्रॉपर्टी लिस्ट से निपटने के दौरान कोई भी इन कार्यों का उपयोग कैसे करता है , अर्थात, जब सूची में निहित गुणों में से प्रत्येक (जो पहले एक से शुरू होने वाला हर दूसरा तत्व होगा) को मैप करने की कोशिश कर रहा है? यह मुझे लगता है कि मानचित्रण फ़ंक्शन को व्यक्तिगत तत्वों के बजाय तत्वों के जोड़े में सूची तक पहुंचने की आवश्यकता होगी।

एक खिलौना उदाहरण के रूप में, कोई संपत्ति की सूची कैसे लेगा और संपत्ति के सभी मूल्यों को इकट्ठा करेगा? यदि यह एक संघ सूची थी तो इसके बजाय यह बहुत आसान होगा:

(mapcar #'cadr '((:prop1 a) (:prop2 b) (:prop3 c))) ;=> (a b c)

मुझे यकीन है कि यह एक लूप के साथ किया जा सकता है, लेकिन यह थोड़ा श्रमसाध्य लगता है और मैं सोच रहा हूं कि क्या यह करने के लिए अधिक मुहावरेदार तरीका है।


कृपया स्पष्ट करें कि क्या आप केवल संपत्ति मूल्यों (जो कि ऐसा लगता है जैसा लगता है, और जो कि आपका mapcarमुट्ठी भर उदाहरण है) करता है या आप संपत्ति प्रतीक और संपत्ति मूल्य के जोड़े पर नक्शा करना चाहते हैं। उत्तरार्द्ध अधिक सामान्य है (अधिक सामान्यतः उपयोगी), मैं अनुमान लगाऊंगा।
ड्रू

@ ड्रू: मुझे सामान्य मामले में अधिक दिलचस्पी है; उदाहरण सबसे सरल था जिसके बारे में मैं सोच सकता था। मैं जानना चाहता हूं कि संपत्ति / मूल्य जोड़ी पर कैसे नक्शा बनाया जाए । यदि उत्तर "लूप" है, तो ऐसा ही हो, लेकिन मैं सोच रहा हूं कि क्या कोई अधिक सुरुचिपूर्ण समाधान है।
दान

आपके पास अपने उदाहरण में जो कुछ भी है वह संपत्ति की सूची नहीं है। संपत्ति सूचियों में तत्वों की संख्या भी होती है, विषम तत्व संपत्ति के नाम होते हैं, यहां तक ​​कि तत्व संपत्ति मूल्य भी होते हैं। आपके पास क्या होगा, शायद, एक पेड़ (सूचियों की एक सूची) कहा जाता है।
wvxvw

जवाबों:


8

आपको संभवतः विभिन्न loopऔर पुनरावृति उत्तर मिलेंगे । AFAIK, ऐसा करने का कोई मुहावरेदार तरीका नहीं है। मुझे यह भी नहीं लगता कि केवल संपत्ति मूल्यों (उन्हें गुणों के साथ जोड़ना नहीं) को संचित करना चाहते हैं।

यहाँ यह करने का एक सरल तरीका है:

(defun prop-values (plist)
  "..."
  (let ((pl    (cdr plist))
        (vals  ()))
    (while pl
      (push (car pl) vals)
      (setq pl  (cddr pl)))
    (nreverse vals)))

अधिक सामान्य मामले के लिए, जहाँ आप एक बाइनरी फ़ंक्शन को प्लिस्ट पर मैप करना चाहते हैं:

(defun map-plist (fn plist)
  "..."
  (let ((pl    plist)
        (vals  ()))
    (while pl
      (push (funcall fn (car pl) (cadr pl)) vals)
      (setq pl (cddr pl)))
    (nreverse vals)))

(setq foo '(a 1 b 2 c 3 d 4 e 5))

(map-plist #'cons foo) ; => ((a . 1) (b . 2) (c . 3) (d . 4) (e . 5))

13

यह शायद एक स्थिति पर निर्भर करेगा। सामान्य तौर पर, अगर मुझे कई नामों के साथ कई मानों को टाई करने की आवश्यकता है, तो मैं एक हैश-टेबल का उपयोग करूंगा, लेकिन अगर मुझे संपत्ति सूची का उपयोग करना है, तो मैं उपयोग करूंगा cl-loop। नीचे कुछ उदाहरण दिए गए हैं:

(cl-loop for (key value) on '(:prop1 a :prop2 b :prop3 c) by 'cddr
         collect value)
;;; (a b c)

और यदि आपके पास एक डेटा-संरचना है जिसे आप अपने उदाहरण में दिखाते हैं:

(cl-loop for (key value) in '((:prop1 a) (:prop2 b) (:prop3 c))
         collect value)
;;; (a b c)

5

मेरे लिए इसका उत्तर यह है कि प्लास्ट को एक एलिस्ट में बदल दिया जाए, जो कि एक समान डेटा-संरचना है, जो कि आधे से गहरी और हेरफेर करने में आसान है।


3
खैर, यह एक जवाब (और अच्छी सलाह) की तरह है, लेकिन एक टिप्पणी का अधिक है।
आकर्षित किया

4

वर्तमान Git HEAD से Emacs के साथ जो Emacs 25 बन जाएगा, आप निम्न कार्य कर सकते हैं, अर्थात, नए seq-partitionफ़ंक्शन के साथ आसानी से मुट्ठी को एक मोड़ दें , और फिर मानक का उपयोग करके alist प्रविष्टियों की प्रक्रिया करें mapcar

(let* ((my-plist (list :a 1 :b 2 :c 3 :more (list 4 5 6)))
       (my-alist (seq-partition my-plist 2))
       (my-reverse-alist (mapcar (lambda (entry)
                                   (let ((prop (car entry))
                                         (val  (cadr entry)))
                                     (list val prop)))
                                 my-alist)))
  (message "my-plist: %s\nmy-alist: %s\nmy-reverse-alist: %s"
           my-plist my-alist my-reverse-alist))
;; my-plist: (:a 1 :b 2 :c 3 :more (4 5 6))
;; my-alist: ((:a 1) (:b 2) (:c 3) (:more (4 5 6)))
;; my-reverse-alist: ((1 :a) (2 :b) (3 :c) ((4 5 6) :more))

seq-partitionडॉक्स का उपयोग करने पर एक नज़र है C-h f seq-partition RET


1

एक तरीका यह उपयोग करने के लिए है -map-indexedसे dashऔर केवल सूची की विषम मूल्यों के परिवर्तन लागू होते हैं:

(-non-nil (-map-indexed (lambda (index item) (when (oddp index) item))
  '(a x b y c z))) ; => (x y z)
(-non-nil (--map-indexed (when (oddp it-index) it) '(a x b y c z))) ; => (x y z)

एक अन्य विचार यह है कि केवल एक हैश-टेबल में एक मुट्ठी को रूपांतरित करना ht<-plistहै ht:

(ht-values (ht<-plist '(a x b y c z) 'equal)) ; (z y x)

ध्यान दें कि हैश-टेबल वस्तुओं के क्रम को संरक्षित नहीं करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.