2010-02-10 11 views
31

से मिलान नहीं कर रहा है मैं emacs बोली का उपयोग करके lisp सीखने की कोशिश कर रहा हूं और मेरे पास एक प्रश्न है। हमें बताएं कि सूची में कुछ सदस्य हैं, जिसके लिए भविष्यवाणी झूठी मूल्यांकन करती है। मैं उन सदस्यों के बिना एक नई सूची कैसे बना सकता हूं? कुछ { A in L: p(A) is true } की तरह। पायथन में फिल्टर फ़ंक्शन है, क्या लिस्प में कुछ समतुल्य है? यदि नहीं, तो मैं यह कैसे करूँ?lisp सूची से परिणामों को फ़िल्टर करें

धन्यवाद

उत्तर

38

इन कार्यों सीएल पैकेज में कर रहे हैं, तो आप उन्हें उपयोग करने के लिए (require 'cl) करने की आवश्यकता होगी:

(remove-if-not #'evenp '(1 2 3 4 5)) 

यह सब भी तर्क से संख्या के साथ एक नई सूची वापस आ जाएगी।

delete-if-not को भी देखें, जो वही करता है, लेकिन इसकी तर्क सूची को संशोधित करता है।

+6

मैं यह इंगित करना चाहता हूं कि सामान्य लिस्प [¹] (http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/ में फ़ंक्शन '#' निकालें- if-not 'को बहिष्कृत नहीं किया गया है। हाइपरस्पेक/बॉडी/fun_removecm__elete-if-not.html) जहां फ़िल्टर लिखा जाएगा '(हटाएं-अगर (पूरक #' शाम) '(1 2 3 4 5))' या बस '(हटाएं-अगर #' oddp ' (1 2 3 4 5)) '- समारोह 'पूरक' हालांकि मेरे ज्ञान के लिए Emacs Lisp में मौजूद नहीं है। –

+1

Pls * cl-lib * पैकेज का उपयोग करें, और ** cl-remove-if-not ** प्रतिस्थापन के रूप में कार्य करें का उपयोग करें। –

19

मैं उसी रात की तलाश में था और Elisp Cookbook पर EmacsWiki पर आया था। The section on Lists/Sequences में फ़िल्टरिंग टेक्निक्स शामिल हैं और दिखाएं कि यह mapcar और delq के साथ कैसे किया जा सकता है। मैं अपने खुद के प्रयोजनों के लिए उपयोग करने के लिए कोड आधुनिकीकरण के लिए था, लेकिन यहाँ मूल है:

;; Emacs Lisp doesn’t come with a ‘filter’ function to keep elements that satisfy 
;; a conditional and excise the elements that do not satisfy it. One can use ‘mapcar’ 
;; to iterate over a list with a conditional, and then use ‘delq’ to remove the ‘nil’ 
;; values. 

    (defun my-filter (condp lst) 
    (delq nil 
      (mapcar (lambda (x) (and (funcall condp x) x)) lst))) 

;; Therefore 

    (my-filter 'identity my-list) 

;; is equivalent to 

    (delq nil my-list) 

;; For example: 

    (let ((num-list '(1 'a 2 "nil" 3 nil 4))) 
    (my-filter 'numberp num-list)) ==> (1 2 3 4) 

;; Actually the package cl-seq contains the functions remove-if and remove-if-not. 
;; The latter can be used instead of my-filter. 
+1

लिंक टूट गया; नया स्थान http://www.emacswiki.org/emacs/ElispCookbook#toc37 है (लेकिन स्टैक ओवरफ्लो मुझे 6 वर्णों से कम संपादित करने नहीं देगा ...) – robru

+0

नया लिंक है: https://www.emacswiki.org/ Emacs/ElispCookbook # toc39 – Cheeso

18

आप अपने कोड में भारी सूचियों में हेरफेर, बजाय बॉयलरप्लेट कोड लिखने और पुनर्रचना की, dash.el आधुनिक कार्यात्मक प्रोग्रामिंग लाइब्रेरी का उपयोग करें पहिया। इसमें प्रत्येक फंक्शन सूचियों, पेड़, फ़ंक्शन एप्लिकेशन और प्रवाह नियंत्रण के साथ काम करने के लिए है जिसे आप कभी कल्पना कर सकते हैं। सभी तत्वों को एक विधेय से मेल रखने के लिए और अन्य लोगों की जरूरत -filter निकालने के लिए:

हित के अन्य कार्यों में शामिल हैं -remove, -take-while, -drop-while:

(-remove (lambda (x) (> x 2)) '(1 2 3 4 5)) ; (1 2)  
(-take-while (lambda (x) (< x 3)) '(1 2 3 2 1)) ; (1 2) 
(-drop-while (lambda (x) (< x 3)) '(1 2 3 2 1)) ; (3 2 1) 

क्या महान है के बारे में dash.el है कि यह anaphoric macros का समर्थन करता है । एनाफोरिक मैक्रोज़ फ़ंक्शंस की तरह व्यवहार करते हैं, लेकिन वे कोड को अधिक संक्षिप्त बनाने के लिए विशेष वाक्यविन्यास की अनुमति देते हैं। एक तर्क के रूप में anonymous function प्रदान करने के बजाय, बस एक s-expression लिखें और स्थानीय मानकों के बजाय it का उपयोग करें, जैसे पिछले उदाहरणों में x। इसी anaphoric मैक्रो एक के बजाय 2 डैश के साथ शुरू:

(--filter (> it 2) '(1 2 3 4 5)) ; (3 4 5) 
(--remove (> it 2) '(1 2 3 4 5)) ; (1 2) 
(--take-while (< it 3) '(1 2 3 2 1)) ; (1 2) 
(--drop-while (< it 3) '(1 2 3 2 1)) ; (3 2 1) 
+0

बहुत बढ़िया लाइब्रेरी, मुझे इंगित करने के लिए धन्यवाद! – JustGage

0
आम तुतलाना साथ

, आप समारोह के रूप में इस लागू कर सकते हैं:

(defun my-filter (f args) 
    (cond ((null args) nil) 
     ((if (funcall f (car args)) 
      (cons (car args) (my-filter f (cdr args))) 
      (my-filter f (cdr args)))))) 

(print 
     (my-filter #'evenp '(1 2 3 4 5))) 
3

Emacs अब पुस्तकालय seq.el के साथ आता है, seq-remove का उपयोग करें।

seq-remove (pred sequence) 
"Return a list of all the elements for which (PRED element) is nil in SEQUENCE." 
0

यह कोई अंतर्निहित (जो बहुत नया है या seq) cl या बिना फिल्टर के संस्करण है आश्चर्य की बात है।

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

इस कार्यान्वयन को सही करने के लिए, nil मार्करों को एक निर्बाध प्रतीक (यानी gensym) के साथ प्रतिस्थापित करने की आवश्यकता है।

(defun my-filter (pred list) 
    (let ((DELMARKER (make-symbol "DEL"))) 
    (delq 
     DELMARKER 
     (mapcar (lambda (x) (if (funcall pred x) x DELMARKER)) 
       list)))) 
0

बिल्ट-इन्स का उपयोग करके सूची से सामान को फ़िल्टर या चुनने के कई तरीके हैं जो लूप से बहुत तेज हैं। अंतर्निहित निकालें- अगर इस तरह इस्तेमाल किया जा सकता है। उदाहरण के लिए, मान लीजिए कि मैं सूची MyList में तत्वों को 3 से 10 छोड़ना चाहता हूं। उदाहरण के रूप में निम्न कोड निष्पादित करें:

(let ((MyList (number-sequence 0 9)) 
     (Index -1) 
    ) 
    (remove-if #'(lambda (Elt) 
        (setq Index (1+ Index)) 
        (and (>= Index 3) (<= Index 5)) 
       ) 
       MyList 
      ) 
) 

आपको '(0 1 2 6 7 8 9) मिलेगा।

मान लीजिए कि आप केवल 3 और 5 के बीच तत्व रखना चाहते हैं। आप मूल रूप से भविष्य में लिखे गए शर्त को फ़्लिप करते हैं।

(let ((MyList (number-sequence 0 9)) 
     (Index -1) 
    ) 
    (remove-if #'(lambda (Elt) 
        (setq Index (1+ Index)) 
        (or (< Index 3) (> Index 5)) 
       ) 
       MyList 
      ) 
) 

आप आप उपयोग कर सकते हैं जो कुछ भी आप विधेय जिसे आप निकालना-यदि करने के लिए प्रदान करना होगा के लिए की जरूरत मिल जाएगा '(3 4 5)

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

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

संबंधित मुद्दे