दो संपत्ति सूचियों को मर्ज करने का कार्य?


11

मुझे इस तरह की दो संपत्ति सूचियों का विलय करने के लिए एक मानक एलिस्फ़ लाइब्रेरी फ़ंक्शन नहीं मिला है:

(setq pl nil)
(setq pl (plist-put pl 'key-1 'value-1))
(setq pl (plist-put pl 'key-2 'value-2))

मैं कुछ के साथ निर्माण कर सकता था dolist, लेकिन इससे पहले कि मैं यह जांचना चाहूँ कि मैं किसी पुस्तकालय में किसी मौजूदा कार्य को नहीं देख रहा हूँ।

अपडेट, टिप्पणियों के आधार पर :

  1. "कई-तरीकों" की टिप्पणी के जवाब में:

मैं कल्पना करूंगा कि ऐसा कोई फ़ंक्शन नहीं है क्योंकि प्रश्न के लिए अलग (और संभवतः मान्य) उत्तर संभव हैं: क्या करना है जब आपके पास अलग-अलग मूल्यों के साथ संपत्ति के नाम की नकल है?

हां, डुप्लिकेट को मर्ज करने के तरीके पर एक सवाल है, लेकिन इसे संबोधित करने के अपेक्षाकृत कम तरीके हैं। मैं दो सामान्य दृष्टिकोण देखता हूं। पहला, तर्क आदेश डुप्लिकेट को हल कर सकता है; जैसे कि क्लोजर के मर्ज में सबसे सही जीत । दूसरा, मर्ज एक उपयोगकर्ता-प्रदान कॉलबैक फ़ंक्शन को सौंप सकता है, जैसा कि रूबी के मर्ज में है

किसी भी मामले में, यह करने के विभिन्न तरीके हैं कि यह कई अन्य भाषा मानक पुस्तकालयों को मर्ज फ़ंक्शन प्रदान करने से नहीं रोकता है। उसी सामान्य तर्क को छँटाई के बारे में कहा जा सकता है, और फिर भी एलीस्प छँटाई की कार्यक्षमता प्रदान करता है।

  1. "क्या आप विस्तृत कर सकते हैं?" / "कृपया वह व्यवहार निर्दिष्ट करें जो आप ठीक-ठीक देख रहे हैं।"

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

(a-merge-function '(k1 1) '(k2 2 k3 3) '(k3 0))

और लौटता है

'(k1 1 k2 2 k3 0))

यह एक सही-जीत शैली होगी, जैसे क्लोजर का मर्ज।

  1. "वे सूची में हैं, तो बस संलग्न हैं?"

नहीं, संपत्ति सूची शब्दार्थ को appendसंरक्षित नहीं करता है । यह:

(append '(k1 1 k2 2) '(k2 0))

यह लौटाता है:

(k1 1 k2 2 k2 0)

एपेंड `सी सोर्स कोड 'में एक अंतर्निहित फ़ंक्शन है।

(संलग्न और बाकी के सत्र)

सभी तर्कों को संक्षिप्त करें और परिणाम को एक सूची बनाएं। परिणाम एक सूची है जिसके तत्व सभी तर्कों के तत्व हैं। प्रत्येक तर्क एक सूची, वेक्टर या स्ट्रिंग हो सकता है। अंतिम तर्क की प्रतिलिपि नहीं बनाई गई है, बस नई सूची की पूंछ के रूप में उपयोग की जाती है।

  1. "और आपका उदाहरण मर्ज की तरह कुछ भी नहीं दिखाता है - यह दो संपत्ति सूचियों को भी नहीं दिखाता है।"

हाँ यह करता है; यह स्टेप बाय स्टेप मर्ज करता है। यह दिखाता है कि एलिस्प की प्रलेखित संपत्ति सूची के कार्यों का उपयोग करके मर्ज कैसे किया जाता है:

(setq pl nil)
(setq pl (plist-put pl 'key-1 'value-1))
(setq pl (plist-put pl 'key-2 'value-2))

बस इसके परिणामस्वरूप आउटपुट मान प्रदर्शित करें pl:

(key-1 value-1 key-2 value-2)

दोहराने के लिए, मैं इस समस्या को हल करने के लिए एक फ़ंक्शन लिखने में सक्षम हूं, लेकिन मैं पहले यह पता लगाना चाहता था कि क्या ऐसा फ़ंक्शन आम उपयोग में कहीं मौजूद है।

अंत में, यदि आपने प्रश्न को अस्वीकार कर दिया है क्योंकि आपको यह स्पष्ट नहीं मिला है, तो मैं पूछूंगा कि अब आप पुनर्विचार करें कि मैं स्पष्ट करने के कुछ प्रयास में गया हूं। यह शोध की कमी नहीं है। "सूचियों" पर एलिस्फ़ दस्तावेज़ में प्रश्न का उत्तर नहीं दिया गया है।


2
वे सूची में हैं, तो बस append?
abo-abo

2
कृपया वह व्यवहार निर्दिष्ट करें जो आप ठीक-ठीक खोज रहे हैं। दो सूचियों को "मर्ज" करने के कई तरीके हैं। और आपका उदाहरण मर्ज की तरह कुछ भी नहीं दिखाता है - यह दो संपत्ति सूचियों को भी नहीं दिखाता है। अब तक, यह सवाल अस्पष्ट के रूप में बंद होना चाहिए। एफडब्ल्यूआईडब्ल्यू, इस बात से अवगत रहें कि प्लिस्ट छाया के सामने एक जोड़ी किसी भी जोड़ी के पास एक ही कुंजी है जो सामने से आगे है। तो विलय का अर्थ हो सकता है कि तत्वों को एक प्लिस्ट से दूसरे तत्वों से पहले डाल दिया जाए, आदि
ड्रू

1
@ abo-abo: यह पता चलता है कि Emacs Lisp मैन्युअल में स्पष्ट है कि संपत्ति के नाम अलग-अलग होने चाहिए
कांस्टेंटाइन

3
सबसे सही सूची जीतने के लिए आपको बस उन सूचियों के क्रम को उलट देना होगा जिन्हें आप पास करते हैं append: (let ((args '((:a 1 :b 1) (:b 2) (:a 3)))) (apply #'append (reverse args))) => (:a 3 :b 2 :a 1 :b 1)जो तब तक ही है (:a 3 :b 2 :a 1)जब तक आप केवल प्लिस्ट कार्यों का उपयोग करते हैं।
तारसियस

1
@ कॉन्स्टेंटाइन: सही, हालांकि न तो लगता है plist-getऔर न ही plist-memberदेखभाल करने के लिए अगर कई समान चाबियाँ हैं। ऐसा लगता है कि वे इस संबंध में एकरूपता का व्यवहार करते हैं (plist-get '(:a "a" :b "b" :a "c") :a) ==> "a":। इस बीच, (plist-put '(:a "a" :b "b" :a "c") :a "d")पहली :aकुंजी का मूल्य बदल जाता है लेकिन दूसरा नहीं।
दान

जवाबों:


8

अंग-मोड, जो Emacs के साथ शामिल है, में एक मर्ज मर्ज फ़ंक्शन होता है:

(defun org-combine-plists (&rest plists)
  "Create a single property list from all plists in PLISTS.
The process starts by copying the first list, and then setting properties
from the other lists.  Settings in the last list are the most significant
ones and overrule settings in the other lists."
  (let ((rtn (copy-sequence (pop plists)))
        p v ls)
    (while plists
      (setq ls (pop plists))
      (while ls
        (setq p (pop ls) v (pop ls))
        (setq rtn (plist-put rtn p v))))
    rtn))

इसका उपयोग करने के लिए आपको (require 'org)पहले फ़ाइल लोड करना होगा। दुर्भाग्य से, यह एक बहुत बड़ी फ़ाइल है, 900 + KB, इसलिए यह उपयोगिता पुस्तकालय के रूप में वास्तव में उपयोग करने योग्य नहीं है। मानक प्लेट पैकेज जैसा कुछ होना अच्छा होगा।

मैंने हाल ही में एक बहुत छोटी शुरुआत की और महसूस किया कि एलिस्ट्स और प्लिस्ट्स के साथ एक ही तरह का व्यवहार नहीं किया जाता है, तर्क-वार - उदाहरण के लिए (प्लिस्ट-गेट लिस्ट KEY) बनाम (एशोक कुंजी लिस्ट), जो कि अनुकूलन (या?) का कुछ दुर्भाग्यपूर्ण अवशेष होना चाहिए? ।

लेकिन, हां, Emacs को एक अच्छी प्लास्ट लाइब्रेरी की आवश्यकता है - मैं अपनी खोज में एक भर में नहीं आया, लेकिन यह अभी भी संभव है कि वहाँ कहीं बाहर है, या फिर हमें एक को शुरू करना होगा और इसे एल्पा / मेलपा पर रखना होगा। ।

एक ही इंटरफेस के साथ एक पुस्तकालय भी अच्छा होगा।


6

मैनुअल पढ़ना और सूची ब्राउज़ करना C-u C-h a plist RETदो संपत्ति सूचियों को मर्ज करने के लिए किसी भी फ़ंक्शन को चालू नहीं करता है। कॉमन लिस्प एक्सटेंशन संपत्ति सूचियों, केवल जगह (पर कार्रवाई करने के लिए विशेष रूप से किसी भी समारोह प्रदान नहीं करते हैं getf/ setf/ ...) समर्थन करते हैं। इसलिए आपको या तो किसी तीसरे पक्ष के पुस्तकालय पर भरोसा करना होगा या अपना स्वयं का रोल करना होगा।

अपना खुद का रोल करना बहुत मुश्किल नहीं है। यह कार्यान्वयन संघर्ष के मामले में अंतिम मूल्य का उपयोग करता है।

(defun plist-merge (&rest plists)
  (if plists
      (let ((result (copy-sequence (car plists))))
        (while (setq plists (cdr plists))
          (let ((plist (car plists)))
            (while plist
              (setq result (plist-put result (car plist) (car (cdr plist)))
                    plist (cdr (cdr plist))))))
        result)
    nil))

(plist-merge '(:x 2 :y 3)
             '(     :y 0 :z 7))
=>            (:x 2 :y 0 :z 7)

अच्छा। आप copy-sequenceपहले क्यों हैं , लेकिन दूसरे नहीं? और इसके अलावा, आप घोंसले को थोड़ा साफ कर सकते हैं cadrऔर cddr
fommil

वास्तव में, org-combine-plists(नीचे) कम या ज्यादा साफ किया गया संस्करण है। मुझे अभी भी समझ नहीं आया कि वे copy-sequenceकार क्यों ले रहे हैं ।
फोमिल

0

मुझे पता है कि यह पहले से ही उत्तर दिया गया है, लेकिन किसी को भी दिलचस्पी है, मैंने इसे orgलागू किया और इस पर कोड गोल्फ का एक सा खेला

(defun plist-merge (&rest plists)
  "Create a single property list from all PLISTS.
Inspired by `org-combine-plists'."
  (let ((rtn (pop plists)))
    (dolist (plist plists rtn)
      (setq rtn (plist-put rtn
                           (pop plist)
                           (pop plist))))))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.