> 1 <

Автор Сообщение

Кира

Members


Статус

25 сообщений

Где: Russia
Род занятий:
Возраст:

#2060   2010-05-18 00:19 GMT+3 часа(ов)      
Есть список :
(1_ TYZ 2_ STAR 3_ 8.09 4_ 16.0)
С помощью REMOVE удалила STAR
Теперь хочу после 2_ вставить новое слово? Как?

ander-skirnir

Members


Статус

227 сообщений
http://lisper.ru
Где: Ukraine
Род занятий: `'`,`',`',
Возраст: 30

#2062   2010-05-18 00:47 GMT+3 часа(ов)      
(defun insert-after (element new-element lst)
(if (null element)
(cons new-element lst)
(loop for cs on lst
when (eql (car cs) element)
do (rplacd cs (cons new-element (cdr cs)))
finally (return lst))))
 
* (insert-after 'd 'e '(a b c d f))
(A B C D E F)
 
* (insert-after nil 'e '(a b c d f))
(E A B C D F)

Кира

Members


Статус

25 сообщений

Где: Russia
Род занятий:
Возраст:

#2063   2010-05-18 00:54 GMT+3 часа(ов)      
А что такое cs?

ander-skirnir

Members


Статус

227 сообщений
http://lisper.ru
Где: Ukraine
Род занятий: `'`,`',`',
Возраст: 30

#2065   2010-05-18 02:05 GMT+3 часа(ов)      
Просто имя переменной. Сокращение от cons, чтобы не запутывать Вас кодом вроде (rplacd cons (cons new-element (cdr cons)).

loop for cs in lst - цикл, в котором переменная cs побывает каждым элементом списка lst
loop for cs on lst - цикл, в котором переменная cs побывает каждой списочной ячейкой списка lst

Например,

loop for x in '(1 2 3) - x будет принимать значения 1 2 3
loop for x on '(1 2 3) - x будет принимать значения (1 2 3), (2 3) (3)

Есть деструктурирующие биндинги, например:

loop for (x . y) in '((1 . 2) (3 . 4) (5 . 6)) - на первой итерации x = 1, y = 2, на второй - x = 3, y = 4, на третьей - x = 5, y = 6.

loop for (hd . tl) on '(1 2 3) - {hd = 1, tl = (2 3)}, {hd = 2, tl = (3)}, {hd = 3, tl = nil}

И есть еще куча других фич.

А вообще, если надумаете изучать макрос loop, не делайте этого, а возьмите сразу iterate.

Кира

Members


Статус

25 сообщений

Где: Russia
Род занятий:
Возраст:

#2067   2010-05-18 02:13 GMT+3 часа(ов)      
Спасибо огромное!Всё понятно!!!!

Fallen_s4e

Members


Статус

114 сообщений
http://lisper.ru
Где: Zimbabwe lisper.ru
Род занятий: fallen_s4e
Возраст: 8

#2068   2010-05-18 03:21 GMT+3 часа(ов)      
(defun f(what after list)
(mapcan #'(lambda(x)
(if (equal x after)
(list x what)
(list x))))
list))


Вообще неплохо бы иметь версию substitute как аналог mapcar->mapcan substitute->???
Чтобы писать (substitute-hz 'after (list after what) *list*)

ander-skirnir

Members


Статус

227 сообщений
http://lisper.ru
Где: Ukraine
Род занятий: `'`,`',`',
Возраст: 30

#2071   2010-05-18 04:46 GMT+3 часа(ов)      
Я стараюсь не использовать ФВП там, где они не востребованы, потому что они рекурсивны и очень проигрывают итеративным процессам. А в случае с mapcan, кроме оверхеда на рекурсиях, присутствует передержка на склеивании результатов. Кроме того, реализация структуроразрушающих эффектов внутри ФВП вроде mapl - выглядит ужасно, а иногда и вовсе может повлиять на механизм рекурсивной аппликации.

Вот тестик:

(defpackage #:insert-after
(:use #:cl #:iter))
 
(in-package #:insert-after)
 
(defun insert-after (element new-element lst)
(if (null element)
(cons new-element lst)
(iter (for cs on lst)
(when (eql (car cs) element)
(rplacd cs (cons new-element (cdr cs))))
(finally (return lst)))))
 
(defun f (what after list)
(if (null after)
(cons what list)
(mapcan #'(lambda(x)
(if (equal x after)
(list x what)
(list x)))
list)))
 
(defvar *list-1* (nconc (make-list 1000000 :initial-element 4) '(q)))
(defvar *list-2* (nconc (make-list 1000000 :initial-element 4) '(q)))
 
(time (f 'new 'q *list-1*))
 
Evaluation took:
0.091 seconds of real time
0.093601 seconds of total run time (0.093601 user, 0.000000 system)
103.30% CPU
181,575,031 processor cycles
8,003,576 bytes consed
 
(time (insert-after 'q 'new *list-2*))
 
Evaluation took:
0.006 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
0.00% CPU
12,753,730 processor cycles
0 bytes consed
 
 
(defvar *list-3* (nconc (make-list 2000000 :initial-element 4) '(q)))
(defvar *list-4* (nconc (make-list 2000000 :initial-element 4) '(q)))
 
(time (f 'new 'q *list-3*))
 
Evaluation took:
1.049 seconds of real time
1.029607 seconds of total run time (0.577204 user, 0.452403 system)
[ Run times consist of 0.796 seconds GC time, and 0.234 seconds non-GC time. ]
98.19% CPU
2,094,228,690 processor cycles
16,000,056 bytes consed
 
(time (insert-after 'q 'new *list-4*))
 
Evaluation took:
0.013 seconds of real time
0.015600 seconds of total run time (0.015600 user, 0.000000 system)
123.08% CPU
25,528,409 processor cycles
0 bytes consed


Как видно, на списке из миллиона элементов, итеративный вариант работает быстрее в 15 раз, а вот уже на списке из 2х миллионов отрыв колоссален - в 80 раз.

asbest

Members


Статус

64 сообщений

Где: Russia
Род занятий:
Возраст: 47

#2078   2010-05-18 14:27 GMT+3 часа(ов)      
Такое предложение:

>(setf a '(1 2 3 4 5 6 7 8))
(1 2 3 4 5 6 7 8)
>(let ((m (member 3 a))) (when m (rplacd m (cons 'new (cdr m)))))
(3 NEW 4 5 6 7 8)
>a
(1 2 3 NEW 4 5 6 7 8)

LinkFly

Members


Статус

152 сообщений

Где: Russia
Род занятий:
Возраст:

#2136   2010-05-24 02:05 GMT+3 часа(ов)      
Что-то я поленился всё это читать.
Но, разве задача не решается так:
(setq my-list '(1_ TYZ 2_ STAR 3_ 8.09 4_ 16.0))
(setf (fourth my-list) 'mysym)

ander-skirnir

Members


Статус

227 сообщений
http://lisper.ru
Где: Ukraine
Род занятий: `'`,`',`',
Возраст: 30

#2193   2010-05-26 10:47 GMT+3 часа(ов)      
Цитата
LinkFly :
Что-то я поленился всё это читать.
Но, разве задача не решается так:
(setq my-list '(1_ TYZ 2_ STAR 3_ 8.09 4_ 16.0))
(setf (fourth my-list) 'mysym)



нет

LinkFly

Members


Статус

152 сообщений

Где: Russia
Род занятий:
Возраст:

#2227   2010-05-31 19:29 GMT+3 часа(ов)      
>Fallen_s4e
Вариант с mapcan красивый, декларативный, но уж больно не производительный )

>ander-skirnir
Думаю, вариант с loop/iterate вполне професиональный, но всё-таки сущностей при этом чуть больше, чем может быть.
И я соглашаюсь с вариантом asbest'a, вот результаты (мой_вариант/вариант_asbest'a чуть лучше по времени):

 
;;; Вставка в список
(require :asdf)
(asdf:oos 'asdf:load-op :iterate)
(use-package :iterate)
 
(defun insert-after-my (elem item ls)
(let* ((ls-part (member item ls))
(ls-after (rest ls-part)))
(if ls-part
(rplacd ls-part (cons elem ls-after)) )
ls))
(insert-after-my 'start '2_ '(1_ TYZ 2_ 3_ 8.09 4_ 16.0))
;;=> (|1_| TYZ |2_| START |3_| 8.09 |4_| 16.0)
 
(defun f (what after list)
(if (null after)
(cons what list)
(mapcan #'(lambda(x)
(if (equal x after)
(list x what)
(list x)))
list)))
 
 
(defun insert-after (element new-element lst)
(if (null element)
(cons new-element lst)
(iter (for cs on lst)
(when (eql (car cs) element)
(rplacd cs (cons new-element (cdr cs))))
(finally (return lst)))))
(insert-after 'start '2_ '(1_ TYZ 2_ 3_ 8.09 4_ 16.0))
 
;;;;;;;;;;;;;; Tests ;;;;;;;;;;;;;;;
(progn
(defparameter *list-my-1* (nconc (make-list 1000000 :initial-element 4) '(q)))
(time (insert-after-my 'new 'q *list-my-1*))
nil)
#|
Evaluation took:
0.006 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
0.00% CPU
14,123,018 processor cycles
0 bytes consed
|#
 
(progn
(defparameter *list-my-2* (nconc (make-list 2000000 :initial-element 4) '(q)))
(member 'q *list-my-2*)
(time (insert-after-my 'new 'q *list-my-2*))
nil)
#|
Evaluation took:
0.012 seconds of real time
0.012001 seconds of total run time (0.012001 user, 0.000000 system)
100.00% CPU
29,117,795 processor cycles
0 bytes consed
|#
 
(progn
(defparameter *list-1* (nconc (make-list 1000000 :initial-element 4) '(q)))
(time (f 'new 'q *list-1*))
nil)
 
#|
Evaluation took:
0.221 seconds of real time
0.220014 seconds of total run time (0.160010 user, 0.060004 system)
[ Run times consist of 0.096 seconds GC time, and 0.125 seconds non-GC time. ]
99.55% CPU
531,441,064 processor cycles
8,015,184 bytes consed
|#
 
(progn
(defparameter *list-2* (nconc (make-list 1000000 :initial-element 4) '(q)))
(member 'q *list-2*)
(time (insert-after 'q 'new *list-2*))
nil)
 
#|
Evaluation took:
0.008 seconds of real time
0.008000 seconds of total run time (0.008000 user, 0.000000 system)
100.00% CPU
18,525,616 processor cycles
0 bytes consed
|#
 
(progn
(defparameter *list-3* (nconc (make-list 2000000 :initial-element 4) '(q)))
(time (f 'new 'q *list-3*))
nil)
 
#|
Evaluation took:
0.436 seconds of real time
0.432027 seconds of total run time (0.280018 user, 0.152009 system)
[ Run times consist of 0.224 seconds GC time, and 0.209 seconds non-GC time. ]
99.08% CPU
1,046,423,394 processor cycles
16,016,224 bytes consed
|#
 
(progn
(defparameter *list-4* (nconc (make-list 2000000 :initial-element 4) '(q)))
(member 'q *list-4*)
(time (insert-after 'q 'new *list-4*))
nil)
 
#|
Evaluation took:
0.015 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
0.00% CPU
37,026,546 processor cycles
0 bytes consed
F slow INSERT-AFTER in 29 times (/ 0.436 0.015)
 
Цитата:
"Как видно, на списке из миллиона элементов, итеративный вариант работает быстрее в 15 раз, а вот уже на списке из 2х миллионов отрыв колоссален - в 80 раз."
Это не так: никакого разрыва нет (SBCLx86 Linux) - 28 против 29 раз.
 
|#
 

отредактировал(а) LinkFly: 2010-06-01 12:48 GMT+3 часа(ов)

LinkFly

Members


Статус

152 сообщений

Где: Russia
Род занятий:
Возраст:

#2228   2010-05-31 19:30 GMT+3 часа(ов)      
А как отформатировать нормально?

Fallen_s4e

Members


Статус

114 сообщений
http://lisper.ru
Где: Zimbabwe lisper.ru
Род занятий: fallen_s4e
Возраст: 8

#2236   2010-05-31 20:40 GMT+3 часа(ов)      
LinkFly, Тэг "code".
ander-skirnir,LinkFly, согласен, медленно, но скорость роста та же. Склеивание здесь дешевое - линейно зависит от длины результата.
> 1 <


Онлайн :

0 пользователь(ей), 33 гость(ей) :