robierzo Posted September 22, 2012 Posted September 22, 2012 I need to convert a list: (51 41 83 10 60 32 46 84) to list: ((51 41)(83 10)(60 32)(46 84)) Regards Quote
marko_ribar Posted September 22, 2012 Posted September 22, 2012 (defun every2nd ( lst ) (vl-remove nil (mapcar '(lambda ( a ) (if (eq (rem (vl-position a lst) 2) 0) a)) lst)) ) (defun groupby2 ( lst ) (mapcar '(lambda ( a b ) (list a b)) (every2nd lst) (every2nd (cdr lst))) ) (groupby2 '(51 41 83 10 60 32 46 84)) M.R. Quote
David Bethel Posted September 22, 2012 Posted September 22, 2012 Maybe : [b][color=BLACK]([/color][/b]setq lst '[b][color=FUCHSIA]([/color][/b]51 41 83 10 60 32 46 84[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b] [b][color=BLACK]([/color][/b]defun lby2 [b][color=FUCHSIA]([/color][/b]l / tmp[b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]while l [b][color=NAVY]([/color][/b]setq tmp [b][color=MAROON]([/color][/b]cons [b][color=GREEN]([/color][/b]list [b][color=BLUE]([/color][/b]nth 0 l[b][color=BLUE])[/color][/b] [b][color=BLUE]([/color][/b]nth 1 l[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b] tmp[b][color=MAROON])[/color][/b] l [b][color=MAROON]([/color][/b]cdr l[b][color=MAROON])[/color][/b] l [b][color=MAROON]([/color][/b]cdr l[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] I would recommend doing some basic error checking for these types of routine ie is the length of the list an even number. -David Quote
Gu_xl Posted September 22, 2012 Posted September 22, 2012 (defun every2 (l) (cond ((and (car l) (cadr l)) (cons (list (car l) (cadr l)) (every2 (cddr l))) ) ((car l) (list l)) ) ) Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 (defun g2 ( l ) (if l (cons (list (car l) (cadr l)) (g2 (cddr l))))) Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 (defun every2nd ( lst ) (vl-remove nil (mapcar '(lambda ( a ) (if (eq (rem (vl-position a lst) 2) 0) a)) lst)) ) (defun groupby2 ( lst ) (mapcar '(lambda ( a b ) (list a b)) (every2nd lst) (every2nd (cdr lst))) ) (groupby2 '(51 41 83 10 60 32 46 84)) Be careful with duplicates... _$ (every2nd '(1 2 3 1 2 3)) (1 3 1 3) For your method, consider perhaps: (defun f ( l / i ) (setq i -1) (vl-remove-if '(lambda ( x ) (= 1 (rem (setq i (1+ i)) 2))) l) ) (defun g2 ( l ) (mapcar 'list (f l) (f (cdr l)))) _$ (g2 '(1 2 3 1 2 3)) ((1 2) (3 1) (2 3)) Quote
Stefan BMR Posted September 22, 2012 Posted September 22, 2012 Three alternatives 1 - recursive - similar to Lee (see l2p function) 2 - using foreach (defun ph1:l2p (l / s r) (foreach x l (if s (setq r (cons (list s x) r) s nil ) (setq s x) ) ) (reverse r) ) 3 - using repeat (defun ph2:l2p (l / r) (repeat (/ (length l) 2) (setq r (append r (list (list (car l) (cadr l)))) l (cddr l) ) ) r ) Quote
robierzo Posted September 22, 2012 Author Posted September 22, 2012 Uffff. I will explore all options, to see which one i choose. I thought it would be easier with mapcar and lambda. Thank you all. Regards. Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 I thought it would be easier with mapcar and lambda. Note that not all tasks are best solved using mapcar. For this particular example, the items in the list need to be processed in pairs, hence mapcar is not best suited for the task since it will process every item in a list consecutively, meaning that you must first manipulate the list before passing it to mapcar. This extra work to manipulate the list is very inefficient where other methods could process the list directly. The mapcar function is just one tool in your AutoLISP toolbox, from which you should choose the best tool for the job. Restricting yourself to solely using mapcar for every task would be like building a house with just a hammer... Quote
marko_ribar Posted September 22, 2012 Posted September 22, 2012 Be careful with duplicates... _$ (every2nd '(1 2 3 1 2 3)) (1 3 1 3) You're right as always Lee... So my first code : (defun every2nd ( lst / x ) (setq x -1) (vl-remove nil (mapcar '(lambda ( a ) (if (eq (rem (setq x (1+ x)) 2) 0) a)) lst)) ) (defun groupby2 ( lst ) (mapcar '(lambda ( a b ) (list a b)) (every2nd lst) (every2nd (cdr lst))) ) (groupby2 '(1 2 3 1 2 3)) Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 No need for the lambda here : (mapcar '(lambda ( a b ) (list a b)) (every2nd lst) (every2nd (cdr lst))) (mapcar 'list (every2nd lst) (every2nd (cdr lst))) Quote
robierzo Posted September 22, 2012 Author Posted September 22, 2012 I can not see post # 11 and following. I get this message: [b]Forbidden[/b] You don't have permission to access /forum/showthread.php on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request. Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 I can not see post # 11 and following. I get this message: [b]Forbidden[/b] You don't have permission to access /forum/showthread.php on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request. This is because you have used "...." in your thread title. Quote
marko_ribar Posted September 22, 2012 Posted September 22, 2012 So, is this the shortest ? (defun every2nd ( lst / x ) (setq x -1) (vl-remove-if-not '(lambda ( a ) (eq (rem (setq x (1+ x)) 2) 0)) lst) ) (defun groupby2 ( lst ) (mapcar 'list (every2nd lst) (every2nd (cdr lst))) ) (groupby2 '(1 2 3 1 2 3)) Quote
Lee Mac Posted September 22, 2012 Posted September 22, 2012 So, is this the shortest? If you were to remain using the vl-remove-if-not function (or vl-remove-if function, as per my earlier post), then those arrangements would most likely be the shortest. Shorter code could obviously be obtained by using alternative methods to generate each list supplied to mapcar: (defun f ( l ) (if l (cons (car l) (f (cddr l))))) (defun g ( l ) (mapcar 'list (f l) (f (cdr l)))) ...Or of course by abandoning mapcar as stated and demonstrated in my earlier posts. Quote
marko_ribar Posted September 24, 2012 Posted September 24, 2012 ;; Group by number by M.R. ;; (defun gn ( l n / f g k q ) (setq k n q l) (defun f ( l n ) (if (and l (> n 0)) (cons (car l) (f (setq q (setq l (cdr l))) (setq n (1- n)))))) (defun g ( l n ) (if q (cons (f q k) (g q k)))) (g q k) ) (gn '(11 21 31 12 22 32) 2) M.R. Quote
Lee Mac Posted September 24, 2012 Posted September 24, 2012 ;; Group by number by M.R. ;; (defun gn ( l n / f g k q ) (setq k n q l) (defun f ( l n ) (if (and l (> n 0)) (cons (car l) (f (setq q (setq l (cdr l))) (setq n (1- n)))))) (defun g ( l n ) (if q (cons (f q k) (g q k)))) (g q k) ) (gn '(11 21 31 12 22 32) 2) Since you are calling the function f recursively, the use of setq (as noted the following expression) is unnecessary, as the values of the symbols l and n are passed as arguments to the f function. (f (setq q [highlight](setq[/highlight] l (cdr l))) [highlight](setq[/highlight] n (1- n))) Also, by renaming the parameters of the f function, you could remove the need for the extra 'state' variables k & q, e.g.: (defun gn ( l n / f g ) (defun f ( a b ) (if (and a (< 0 b)) (cons (car a) (f (setq l (cdr a)) (1- b))) ) ) (defun g ( l n ) (if l (cons (f l n) (g l n)))) (g l n) ) However, note further that the function g is also superfluous since it is identical to the function in which it is defined: (defun gn ( l n / f ) (defun f ( a b ) (if (and a (< 0 b)) (cons (car a) (f (setq l (cdr a)) (1- b))) ) ) (if l (cons (f l n) (gn l n))) ) Quote
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.