Jump to content

Break a list in two sub lists


MJLM

Recommended Posts

I want to break a list in two sub lists like that:

 

List: (a b c d e f g)

 

And get

 

L1 as (a b c d) and L2 as (e f g).

 

It s easy to get the second L2 with (member e ls) and frankly i can get the L1 with a "foreach" and "cons" function but it seems to much of a code for that. Is there a function like "member" to get the L1 faster and with less code? A vl-something function maybe?

 

Thank you

Link to comment
Share on other sites

How about throwing a couple reverses in there? So getting L1 would be just like getting L2:

 

(reverse (member d (reverse ls)))

 

I'm definitely no lisp expert, so take my suggestions with a grain of salt.

Link to comment
Share on other sites

This function by Gile Chanteau:

 

You supply n which is number of element in first list

and l the list.

 

defun breakAt (n l / r)
 (while (and l (< 0 n))
   (setq r (cons (car l) r)
  l (cdr l)
  n (1- n)
   )
 )
 (list (reverse r) l)
)

 

As an alternative you could use function trunc

also by by Gile Chanteau

 

You supply expr and the list. In your case expr woulld be e

 

(defun trunc	(expr lst)
 (if (and lst
   (not (equal (car lst) expr))
     )
   (cons (car lst) (trunc expr (cdr lst)))
 )
)

 

So your first list would be:

 

(setq L1 (trunc e  lst))

 

The second one:

(setq L2 (member e lst)

)

Edited by ymg3
Link to comment
Share on other sites

Another:

(defun breakatitem ( x l / r )
   (setq l (vl-member-if '(lambda ( y ) (setq r (cons y r)) (equal x y)) l))
   (list (reverse (cdr r)) l)
)

_$ (breakatitem 'e '(a b c d e f g))
((A B C D) (E F G))
_$ (breakatitem 'h '(a b c d e f g))
((A B C D E F) nil)
_$ (breakatitem 'a '(a b c d e f g))
(nil (A B C D E F G))

Link to comment
Share on other sites

@ymg & LM :thumbsup:

 

sorry mine is out of topic, this code just split equally.

Just for sharing if others see this thread for similarity.

split by division or length with opt T or nil

(defun split (lst len opt / ls l i) ; opt, T= by division or nil=by length
(setq i 1 l '() len (if opt (/ (length lst) len) len))
 (while lst
   (setq l (append  l (list(car lst))))
   (if
   (zerop (rem i len))
(setq ls (cons l ls) l nil)
   ) 
   (setq i (1+ i) lst (cdr lst))
 ) ;_ end of foreach
 (if l
   (append (reverse ls) (list  l))
   (reverse ls)
 ) ;_ end of if
) ;_ end of defun

 

Test:

(setq a '(1 2 3 4 5 6 7 8 9 0))

; split by division 
(split a 3 t)
;((1 2 3) (4 5 6) (7 8 9) (0)) 
(split a 2 t)
;((1 2 3 4 5) (6 7 8 9 0))
(split a 1 t)
;((1 2 3 4 5 6 7 8 9 0)) 

; split by length
(split a 3 nil)
;((1 2 3) (4 5 6) (7 8 9) (0))
(split a 2 nil)
;((1 2) (3 4) (5 6) (7  (9 0))
(split a 1 nil)
;((1) (2) (3) (4) (5) (6) (7) ( (9) (0))

p/s: The CODE tag font lowercase "L" is very similar number "1", can't differentiate in a glance?!

Edited by hanhphuc
Link to comment
Share on other sites

  • 1 year later...

Hi,

 

Can someone help me with my problem?

For example, I have list like this:

(a 1 2 3 4 a 5 6 7 8 )

and I would like to get something like this:

((1 2 3 4) (5 6 7 8 ))

Link to comment
Share on other sites

Hi,

 

Can someone help me with my problem?

For example, I have list like this:

(a 1 2 3 4 a 5 6 7 8 )

and I would like to get something like this:

((1 2 3 4) (5 6 7 8 ))

 

What is the criteria that the programmer should consider to come up with this outcome ?

Link to comment
Share on other sites

What is the criteria that the programmer should consider to come up with this outcome ?

I would like to divide list by separator.

 

better example below:

1) (setq mylist (list "sep" "a" "b" "c" "sep" "d" "e" "f")
or
2) (setq mylist (list "a" "b" "c" "sep" "d" "e" "f")
or
3) (setq mylist (list "a" "b" "c" "d" "e" "sep" "f")

And now i would like to write function with that will split mylist by separator:

(List_sep mylist "sep")

Expected result of function List_sep:

1) (("a" "b" "c")("d" "e" "f"))
or
2) (("a" "b" "c")("d" "e" "f"))
or
3) (("a" "b" "c" "d" "e")("f"))

 

I wrote lisp but it doesn't work:

(defun LIST_sep (lista Sep / el res)
(setq el "")
(foreach % lista
	(if (wcmatch % (strcat Sep "*"))
		(setq 
			res (cons el res)
			el ""
		)
		(if (atom el)
			(setq el (cons % (list el)))
			(setq el (cons % el))
		)
	)
)
(setq res (cons el res))
(vl-remove "" res)
)

Edited by ziele_o2k
Link to comment
Share on other sites

Try this:

 

(defun _div:by:sep (lst sep / n f out all)
 ;; Tharwat 19.08.2015	;;
 (setq n 0)
 (repeat (length lst)
   (while (and (/= (setq f (nth n lst)) sep)
               f
               )
     (setq out (append out (list f))
           n   (1+ n)
           )
     )
   (if out
     (setq all (cons out all)
           out nil
           )
     )
   (setq n (1+ n))
   )
 (reverse all)
 )

Link to comment
Share on other sites

Thank you.

I have to make some changes that lisp will work in case shown below:

(setq mylist (list "sepa" "a" "b" "c" "sepa" "d" "e" "f"))
(_div:by:sep mylist "se")

Result:

(("a" "b" "c")("d" "e" "f"))

Link to comment
Share on other sites

Here's another:

(defun div ( d l / m r )
   (foreach x l
       (if (= x d)
           (if   m (setq r (cons (reverse m) r) m nil))
           (setq m (cons x m))
       )
   )
   (reverse (if m (cons (reverse m) r) r))
)

_$ (div "sep" '("a" "b" "c" "sep" "d" "e" "f"))
(("a" "b" "c") ("d" "e" "f"))

Link to comment
Share on other sites

Another, recursive solution:

(defun div ( d l / r )
   (cond
       (   (= (car l) d) (div d (cdr l)))
       (   (setq l (vl-member-if '(lambda ( x ) (setq r (cons x r)) (= x d)) l))
           (cons (reverse (cdr r)) (div d (cdr l)))
       )
       (   r (list (reverse r)))
   )
)

Link to comment
Share on other sites

My version

(defun div ( d l / m r )
   (foreach x l
       (if (wcmatch x (strcat d "*"))
           (if   m (setq r (cons (reverse m) r) m nil))
           (setq m (cons x m))
       )
   )
   (reverse (if m (cons (reverse m) r) r))
)

(div "se" '("a" "b" "c" "sep" "d" "e" "f"))
(("a" "b" "c") ("d" "e" "f"))

Link to comment
Share on other sites

Try this:

 

(defun _div:by:sep (lst sep / n f out all)
 ;; Tharwat 19.08.2015	;;
 (setq n 0)
 (repeat (length lst)
   (while (and ([color="blue"]wcmatch [/color](setq f (nth n lst)) sep)
               f
               )
     (setq out (append out (list f))
           n   (1+ n)
           )
     )
   (if out
     (setq all (cons out all)
           out nil
           )
     )
   (setq n (1+ n))
   )
 (reverse all)
 )

 

Thank you.

I have to make some changes that lisp will work in case shown below:

(setq mylist (list "sepa" "a" "b" "c" "sepa" "d" "e" "f"))
(_div:by:sep mylist "se")

Result:

(("a" "b" "c")("d" "e" "f"))

 

I see that you have asked for something else after your first one ! anyway , just replace in my previous program the /= with the wcmatch function as modified in the quotes above.

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