Lee Mac Posted March 3, 2009 Share Posted March 3, 2009 This may be a stupid question, but I am not completely awake today. If I have a list, say (a b c d e f) and I want to retrieve say, (c d e) from it, how is the best way to do this without going through a load of cad, cadr, cdr, cddr etc etc. I have looked at nth, but this seems to only retrieve a single member. Thanks Lee Quote Link to comment Share on other sites More sharing options...
David Bethel Posted March 3, 2009 Share Posted March 3, 2009 Depends on how you state the querry Do you want the 3rd 4th and 5th atom? Do you want to drop the 1st 2 atoms and the last? Do you want just c d e? -David Quote Link to comment Share on other sites More sharing options...
wizman Posted March 3, 2009 Share Posted March 3, 2009 lee, here's another way: (mapcar 'read (mapcar 'chr (vl-string->list (substr (apply 'strcat (mapcar 'vl-princ-to-string '(a b c d e f)) ) ;_ end_apply 3 3 ) ;_ end_substr ) ;_ end_read ) ;_ end_list ) ;_ end_apply *EDIT* resultant updated (CDE) to (C D E) Quote Link to comment Share on other sites More sharing options...
ASMI Posted March 3, 2009 Share Posted March 3, 2009 Another code: (defun Extract-List-Items(Lst Items / oLst) (reverse (foreach i Items (setq oLst(cons(nth i Lst)oLst)) ) ) ) Test: Command: (Extract-List-Items '(a b c d e f) '(1 2 3)) (B C D) Command: (Extract-List-Items '(a b c d e f) '(0 5)) (A F) Command: (Extract-List-Items '(a b c d e f) '(0 1 344)) (A B nil) Quote Link to comment Share on other sites More sharing options...
ASMI Posted March 3, 2009 Share Posted March 3, 2009 And one more: (defun Extract-List-Items(Lst Items) (mapcar '(lambda(i)(nth i Lst))Items) ) Command: (Extract-List-Items '(a b c d e f) '(0 4 5)) (A E F) Quote Link to comment Share on other sites More sharing options...
VovKa Posted March 3, 2009 Share Posted March 3, 2009 (defun GetSubList (InList Strt Len /) (if InList (if (> Strt 0) (GetSubList (cdr InList) (1- Strt) Len) (if (> Len 0) (cons (car InList) (GetSubList (cdr InList) 0 (1- Len))) ) ) ) ) Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted March 3, 2009 Author Share Posted March 3, 2009 Many thanks for the replies Guys, some very ingenius solutions to such a problem. I shall peruse the various replies and see which fits my coding the best Thanks a lot guys Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted March 4, 2009 Author Share Posted March 4, 2009 And one more: (defun Extract-List-Items(Lst Items) (mapcar '(lambda(i)(nth i Lst))Items) ) Command: (Extract-List-Items '(a b c d e f) '(0 4 5)) (A E F) Superb coding here ASMI (as are all the other examples).. - loving the simplicity of this one I wonder why LISP never included a function similar to "substr" for use with lists, so that one could select a section of a list... Quote Link to comment Share on other sites More sharing options...
David Bethel Posted March 4, 2009 Share Posted March 4, 2009 I don't think that I have ever run into a scenario where I know the placement of the atoms to extract other than point values. But here is a quasi substr for lists. Remember it would (nth) positions not character places. [b][color=BLACK]([/color][/b]defun sublst [b][color=FUCHSIA]([/color][/b]l s n / tmp[b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]repeat n [b][color=NAVY]([/color][/b]setq tmp [b][color=MAROON]([/color][/b]cons [b][color=GREEN]([/color][/b]nth s l[b][color=GREEN])[/color][/b] tmp[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]setq s [b][color=MAROON]([/color][/b]1+ s[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]reverse tmp[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b] [b][color=BLACK]([/color][/b]setq l1 '[b][color=FUCHSIA]([/color][/b]1 2 3 4 5 6 7[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b] [b][color=BLACK]([/color][/b]prin1 [b][color=FUCHSIA]([/color][/b]sublst l1 2 4[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b] -David Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted March 4, 2009 Author Share Posted March 4, 2009 I don't think that I have ever run into a scenario where I know the placement of the atoms to extract other than point values. Many thanks for your contibution David, very intuitive solution. To answer your question of why I would need such a function: When using DCL with my LISP I have a main list of variables whose values I add_list to a popup_list. However, I have two such popup_lists and the values that populate the second list are dependent upon the selection the user makes from the first. Therefore, when the user selects the first option, I needed take a section of the main list to populate the second popup_list... Of course, I could've just written up the new list for each combination of selections, but where's the fun in that... Thanks once again,, Lee Quote Link to comment Share on other sites More sharing options...
taner Posted March 5, 2009 Share Posted March 5, 2009 anther one: (defun remove-lst-items (lst itemlst / i) (setq i -1) (vl-remove-if '(lambda (x) (member (setq i (1+ i)) itemlst ) ) lst ) ) (defun hold-lst-items (lst itemlst / i) (setq i -1) (vl-remove-if-not '(lambda (x) (member (setq i (1+ i)) itemlst ) ) lst ) ) _$ (remove-lst-items '(a b c d e f) '(0 4 5)) (B C D) _$ (hold-lst-items '(a b c d e f) '(0 4 5)) (A E F) Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted March 5, 2009 Author Share Posted March 5, 2009 Nice one Taner, always nice to see an alternative approach - never knew there'd be this many solutions to the same problem... Quote Link to comment Share on other sites More sharing options...
taner Posted March 5, 2009 Share Posted March 5, 2009 there is anther code of sublst. (defun remove-lstmn (m n lst / j) ; remove the items m~n (setq j -1) (vl-remove-if '(lambda (x) (and (setq j (1+ j)) (<= m j) (>= n j) ) ) lst ) ) (defun hold-lstmn (m n lst / j) ; hold the items m~n (setq j -1) (vl-remove-if-not '(lambda (x) (and (setq j (1+ j)) (<= m j) (>= n j) ) ) lst ) ) _$ lst (1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1) _$ (remove-lstmn 3 6 lst) (1 2 3 8 9 8 7 6 5 4 3 2 1) _$ (hold-lstmn 3 6 lst) (4 5 6 7) _$ Quote Link to comment Share on other sites More sharing options...
CAB Posted March 5, 2009 Share Posted March 5, 2009 Another variation: ;; CAB 10/15/2005 ;;+++++++++++++++++++++++++++++++++++++++++++++++++++++ ;; Return a sub list starting at the nth position and ;; with the number of items specified by num 0= all remaining items ;;+++++++++++++++++++++++++++++++++++++++++++++++++++++ (defun nth+ (lst idx num / newlst) (and (or (numberp num) (setq num 0)) ; force all (zerop num) ; if zero (setq num (length lst)) ; all ) (repeat num (setq newlst (cons (nth idx lst) newlst) idx (1+ idx)) ) (reverse (vl-remove nil newlst)) ) (defun c:test() (print (nth+ '(1 2 3 4 5) 0 2)) ; |-> (1 2) (print (nth+ '(1 2 3 4 5) 3 2)) ; |-> (4 5) (print (nth+ '(1 2 3 4 5) 4 5)) ; |-> (5) (print (nth+ '(1 2 3 4 5) 6 2)) ; |-> nil (print (nth+ '(1 2 3 4 5) 2 0)) ; |-> (3 4 5) (princ) ) Quote Link to comment Share on other sites More sharing options...
uddfl Posted March 10, 2009 Share Posted March 10, 2009 Let's say I have a list: (setq alist '(a b b c)) How do I retrieve the value of "b"? do I have to use 'if' functions on every one of the list elements to compare them with the rest, or is there a shorter way? Quote Link to comment Share on other sites More sharing options...
uddfl Posted March 10, 2009 Share Posted March 10, 2009 Let's say I have a list: (setq alist '(a b b c)) How do I retrieve the value of "b"? do I have to use 'if' functions on every one of the list elements to compare them with the rest, or is there a shorter way? OK I am trying to learn the mapcar function, as it seems to apply to this. What am I doing Rong here? (setq alist '(a b b c)) (setq list-index 0 listlength (length alist)) ;;; determine if two elements of the list are equal (repeat listlength (setq element (nth list-index alist)) (if (mapcar 'equal element alist) ; [b]<[color="DarkRed"] What's wrong with this[/color]?[/b] (setq repeated_item element) ) (setq list-index (1+ list-index)) ) It doesn't like that I quote the list in the mapcar function error: bad argument type: listp a Thanks in advance for any enlightment. Quote Link to comment Share on other sites More sharing options...
Se7en Posted March 10, 2009 Share Posted March 10, 2009 > What's wrong with this? Almost everything; mapcar only transforms (goes thru, iterates, maps, etc) a list. (setq alist '(a b b c) inx 0) (mapcar '(lambda ( x ) (if (eq x 'b) (setq inx (1+ inx)))) alist) Quote Link to comment Share on other sites More sharing options...
uddfl Posted March 10, 2009 Share Posted March 10, 2009 > What's wrong with this? Almost everything; mapcar only transforms (goes thru, iterates, maps, etc) a list. (setq alist '(a b b c) inx 0) (mapcar '(lambda ( x ) (if (eq x 'b) (setq inx (1+ inx)))) alist) Oh. I see. mapcar creates the iteration, which means I don't need the repeat function. I'm such an ass, I knew it was a lot easier than I thought. I still need to understand lambda too... thank you much, Se7en. Quote Link to comment Share on other sites More sharing options...
Se7en Posted March 10, 2009 Share Posted March 10, 2009 Oh. I see. mapcar creates the iteration, which means I don't need the repeat function. I'm such an ass, I knew it was a lot easier than I thought. I still need to understand lambda too... thank you much, Se7en. *lmao* no problem. Lambda is just an anonymous function. Where "(defun name ( / )" is a named function, replace all that with "(lambda ( / )" and you got yourself a function without a name. If you need a function several time throughout a program you give it a name right? (defun name ( / )... Well if you need a function only once you can use use (lambda ( / ) in it place. get it? Quote Link to comment Share on other sites More sharing options...
CAB Posted March 10, 2009 Share Posted March 10, 2009 Another solution: _$ (setq lst '(1 2 3 3 4 5)) (1 2 3 3 4 5) _$ (vl-remove-if-not '(lambda(x) (equal 3 x)) lst) (3 3) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.