Jump to content

Section of List


Lee Mac

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 41
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    10

  • uddfl

    10

  • CAB

    9

  • Se7en

    4

Top Posters In This Topic

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

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

(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)))
     )
   )
 )
)

Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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... :P

 

Thanks once again,,

 

Lee

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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)
_$ 

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

> 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)

Link to comment
Share on other sites

> 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.
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...