2010-04-21 14 views
15

में नेस्टेड कोष्ठकों दूर करने के लिए कैसे मैं इस तरह के रूप मेंकैसे लिस्प

(unnest '(a b c (d e) ((f) g))) => (a b c d e f g) 
    (unnest '(a b))     => (a b) 
    (unnest '(() ((((a))))()))  => (a) 

धन्यवाद

आम लिस्प में रिकर्सिवली नेस्टेड कोष्ठकों को हटा सकते हैं
+18

आप कोष्ठक नहीं हटाते हैं। पेंटिचेस सूचियों के लिए मुद्रित प्रतिनिधित्व का सिर्फ एक पहलू हैं। आप जो कर रहे हैं वह सूक्ष्म सूचियां है। – Svante

उत्तर

3

उदाहरण के लिए आप इस तरह यह निर्धारित कर सकते हैं:

(defun unnest (x) 
    (labels ((rec (x acc) 
    (cond ((null x) acc) 
     ((atom x) (cons x acc)) 
     (t (rec (car x) (rec (cdr x) acc)))))) 
    (rec x nil))) 
+0

धन्यवाद एक buch ... – bubdada

1

चीजों को हटाने के लिए लिस्प में remove फ़ंक्शन है। यहां मैं एक संस्करण REMOVE-IF का उपयोग करता हूं जो प्रत्येक आइटम को हटा देता है जिसके लिए एक भविष्य सत्य है। मैं परीक्षण करता हूं कि क्या चीज एक संश्लेषण है और यदि सत्य हो तो इसे हटा दें।

आप, कोष्ठक हटाने इस समारोह को देखने के लिए चाहते हैं:,

(defun unnest (thing) 
    (read-from-string 
    (concatenate 
    'string 
    "(" 
    (remove-if (lambda (c) 
       (member c '(#\(#\)))) 
       (princ-to-string thing)) 
    ")"))) 

नोट हालांकि, के रूप में Svante का उल्लेख है, एक नहीं आमतौर पर कोष्ठक 'हटाने' है।

14
(defun flatten (l) 
    (cond ((null l) nil) 
     ((atom l) (list l)) 
     (t (loop for a in l appending (flatten a))))) 
6
(defun flatten (l) 
    (cond ((null l) nil) 
     ((atom (car l)) (cons (car l) (flatten (cdr l)))) 
     (t (append (flatten (car l)) (flatten (cdr l)))))) 
16

यहाँ मैं करना चाहते हैं क्या करना है:

(ql:quickload "alexandria") 
(alexandria:flatten list) 

कि मुख्य रूप से काम करता है, क्योंकि मैं Quicklisp पहले से ही स्थापित है।

+13

तो मामूली! यह मुख्य रूप से काम करता है क्योंकि आपने * क्विकलिस्पी पहले ही बनाया है। –

0
(defun unnest (somewhat) 
    (cond 
    ((null somewhat) nil) 
    ((atom somewhat) (list somewhat)) 
    (t 
    (append (unnest (car somewhat)) (unnest (cdr somewhat)))))) 
4

मुझे एहसास है कि यह एक पुराना धागा है, लेकिन यह पहली बार है जब मैं Google lisp flatten पर आता हूं। मैंने जो समाधान खोजा है वह ऊपर चर्चा की गई है, लेकिन प्रारूपण थोड़ा अलग है। मैं इसे समझाऊंगा जैसे कि आप लापरवाही के लिए नए हैं, क्योंकि जब मैं पहली बार इस सवाल को गुगल करता था, तो ऐसा लगता है कि अन्य भी होंगे।

(defun flatten (L) 
"Converts a list to single level." 
    (if (null L) 
     nil 
     (if (atom (first L)) 
      (cons (first L) (flatten (rest L))) 
      (append (flatten (first L)) (flatten (rest L)))))) 

उन नए लोगों के लिए, यह एक संक्षिप्त सारांश है।

निम्न पंक्ति वाणी एक समारोह कहा जाता है एक खाली सूची के लिए तर्क एल

(defun flatten (L) 

साथ समतल चेकों नीचे लाइन।

(if (null L) 

अगली पंक्ति शून्य हो जाती है क्योंकि एटीओएम नील एक प्रविष्टि (एटीओएम) के साथ एक सूची घोषित करता है। यह रिकर्सन का मूल मामला है और फ़ंक्शन को कब रुकना है, यह जानने देता है। यह जांचने के बाद की रेखा यह देखने के लिए कि सूची में पहला आइटम किसी अन्य सूची के बजाय परमाणु है या नहीं।

 (if (atom (first L)) 

फिर, अगर ऐसा है, यह प्रत्यावर्तन इस परमाणु चपटा सूची है कि समारोह उत्पन्न होगा के बाकी के साथ संयुक्त का एक चपटा सूची बनाने के लिए उपयोग करता है। विपक्ष एक परमाणु को एक और सूची के साथ जोड़ता है।

  (cons (first L) (flatten (rest L))) 

यदि यह एक परमाणु नहीं है, तो हम उस पर समतल है, क्योंकि यह एक और सूची इसके अंदर आगे सूचियों हो सकता है है।

  (append (flatten (first L)) (flatten (rest L)))))) 

संलग्न कार्य दूसरी सूची की शुरुआत में पहली सूची जोड़ देगा। यह भी ध्यान रखें कि हर बार जब आप lisp में फ़ंक्शन का उपयोग करते हैं, तो आपको इसे कोष्ठक से घिरा होना होगा। यह मुझे पहले उलझन में डाल दिया।

+0

और क्या यह पूंछ रिकर्सिव है? – amirteymuri

1

यह एक संचयी आधारित दृष्टिकोण है। स्थानीय फ़ंक्शन % flatten पूंछ का एक संचयक रखता है (दाएं सूची का हिस्सा जो पहले से ही फ़्लैट किया गया है)। जब भाग को फ़्लैट किया जाना चाहिए (सूची के भाग छोड़ दिया गया है) खाली है, यह पूंछ लौटाता है। जब भाग को फ़्लैट किया जाना एक गैर-सूची है, तो वह उस भाग को पूंछ पर उपसर्ग करता है। जब भाग को फ़्लैटेड किया जाता है तो यह एक सूची है, यह सूची के आराम को वर्तमान पूंछ के साथ फ़्लैट करता है, फिर उस परिणाम का उपयोग सूची के पहले भाग को फ़्लैट करने के लिए पूंछ के रूप में करता है।

(defun flatten (list) 
    (labels ((%flatten (list tail) 
      (cond 
       ((null list) tail) 
       ((atom list) (list* list tail)) 
       (t (%flatten (first list) 
          (%flatten (rest list) 
             tail)))))) 
    (%flatten list '()))) 

CL-USER> (flatten '((1 2) (3 4) ((5) 6) 7)) 
(1 2 3 4 5 6 7) 
1

मैं जानता हूँ कि इस सवाल का वास्तव में पुराने है, लेकिन मैंने देखा है कि कोई भी धक्का/nreverse मुहावरा इस्तेमाल किया, इसलिए मैं यहाँ कि अपलोड कर रहा।

फ़ंक्शन reverse-atomize प्रत्येक "परमाणु" निकालता है और इसे अगली कॉल के output में डाल देता है। अंत में यह एक flattened सूची उत्पन्न करता है जो पीछे की तरफ है, जिसे atomize फ़ंक्शन में nreverse फ़ंक्शन के साथ हल किया गया है।

(defun reverse-atomize (tree output) 
    "Auxillary function for atomize" 
    (if (null tree) 
     output 
     (if (atom (car tree)) 
      (reverse-atomize (cdr tree) (push (car tree) output)) 
      (reverse-atomize (cdr tree) (nconc (reverse-atomize (car tree) 
                   nil) 
               output))))) 

(defun atomize (tree) 
    "Flattens a list into only the atoms in it" 
    (nreverse (reverse-atomize tree nil))) 

तो बुला atomize '((a b) (c) d) इस तरह दिखता है:

(A B C D) 

और यह स्थिति तब आती है यदि आप reverse-atomize कॉल करने के लिए थे reverse-atomize '((a b) (c) d) साथ:

(D C B A) 

push, nreverse जैसे कार्यों का उपयोग कर जैसे लोग, और nconc क्योंकि वे अपने संबंधितसे कम रैम का उपयोग करते हैं 210, reverse, और append फ़ंक्शंस। ऐसा कहा जा रहा है कि reverse-atomize की डबल रिकर्सिव प्रकृति इसके रैम ifications के साथ आती है।