robierzo Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
marko_ribar Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
David Bethel Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
Gu_xl Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share Posted September 22, 2012 (defun g2 ( l ) (if l (cons (list (car l) (cadr l)) (g2 (cddr l))))) Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
Stefan BMR Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
robierzo Posted September 22, 2012 Author Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
robierzo Posted September 22, 2012 Author Share Posted September 22, 2012 O.K. making way....Thanks Quote Link to comment Share on other sites More sharing options...
marko_ribar Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
robierzo Posted September 22, 2012 Author Share 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 Link to comment Share on other sites More sharing options...
robierzo Posted September 22, 2012 Author Share Posted September 22, 2012 Now I can see them. Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
marko_ribar Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted September 22, 2012 Share 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 Link to comment Share on other sites More sharing options...
robierzo Posted September 23, 2012 Author Share Posted September 23, 2012 O.K. making way....Thanks Quote Link to comment Share on other sites More sharing options...
marko_ribar Posted September 24, 2012 Share 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 Link to comment Share on other sites More sharing options...
Lee Mac Posted September 24, 2012 Share 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 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.