Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > LISP > рекурсивно заменить элемент в списке


Автор: sw04 8.11.2007, 23:41
Код

(setq a '(a b x d x))

(defun replace(x n v)
    (cond ((NULL v ) 0)
    (t
        (print (car v))
        (cond ((eq (car v) x) (setq v (cons n (cdr v)))))
        (replace x n (cdr v))
        (print v)
    )
    )
)
(replace 'x 'n a)

в упор не хочет заменить x на n :( 
башка уже трещит

Автор: skyboy 9.11.2007, 00:41
как там функция проверки, является ли аргумент списком? listp? 
тогда вроде такого:
Код

(defun 
 replace
 (needle replacement source)
 (if
  (NULL source)
  (return nil)
  (if
   (listp source)
   (if 
    (eq needle (car source))
    (cons replacement (replace needle replacement (cdr source))) 
    (if
     (listp (car source))
     (return (cons (replace needle replacement (car source)) (replace needle replacement (cdr source))))
     (return (cons (car source) (replace needle replacement (cdr source))))
    )
   )
   (if
    (eq needle source) 
    (return replacement)
    (return source)
   )
  )
 ) 
)

правда, может, тебе как раз с побочными эффектами функция нужна, а не "чистая"...

Добавлено через 1 минуту и 32 секунды
естественно, куча проверок напрямую к функциональности кода не относится...

Автор: VH_ 10.11.2007, 22:56
Код

(defun REPLACE (_old _new _list)
 (cond
  ((null _list) nil)
  ((equal (car _list) _old) (cons _new (REPLACE _old _new (cdr _list))))
  (T (cons (car _list) (REPLACE _old _new (cdr _list))))))

Код
(defun REPLACE (_old _new _list)
 (if _list
  (cons
   (if (equal (car _list) _old)
    _new
    (car _list))
   (REPLACE _old _new (cdr _list)))))

Автор: Eduard1 28.1.2009, 16:09
А как можно рекурсивно заменить N-ый элемент в списке (указав  номер заменяемого элемента)? 

Имеется список lst 
(setq lst '(S L O V O)) 

переменные: 
X - новый символ  
N - номер элемента  

(defun Replace (X N lst) 
     (cond 
         ( (null lst) nil) 
         ..... 
         ..... 
         .....
     ) 


В итоге должно получиться: 
> (Replace 'A 5 lst) 
(S L O V A)

Автор: VH_ 28.1.2009, 16:35
Код

(defun F (X N L)
 (cond
  ((null L) nil)
  ((= N 0) (cons X (cdr L))) ; отцы LISPа нам завещали, что номера элементов списка начинаются с 0 (нуля)
  ((> N 0) (cons (car L) (F X (1- N) (cdr L))))
  (T L)))


Автор: k0rvin 24.1.2010, 09:58
Цитата(sw04 @ 8.11.2007,  23:41)
Код

(setq a '(a b x d x))

(defun replace(x n v)
    (cond ((NULL v ) 0)
    (t
        (print (car v))
        (cond ((eq (car v) x) (setq v (cons n (cdr v)))))
        (replace x n (cdr v))
        (print v)
    )
    )
)
(replace 'x 'n a)

в упор не хочет заменить x на n :( 
башка уже трещит

Код

(defun replace (a b xs &key (test #'eq))
  (loop for x in xs collect (if (funcall test x a) b x)))

Автор: VH_ 24.1.2010, 16:37
>k0rvin
Задание: «...рекурсивно заменить элемент в списке...»

Автор: k0rvin 24.1.2010, 20:26
Цитата(VH_ @ 24.1.2010,  16:37)
>k0rvin
Задание: «...рекурсивно заменить элемент в списке...»

а, т.е. полностью свой велосипед, даже без map'а? =)

ну тогда
Код

(defun replace2 (a b xs &key (test #'eq))
  (labels ((rec (xs)
             (if (null xs)
                 nil
                 (destructuring-bind (x &rest xs) xs
                   (cons (if (funcall test x a) b x)
                         (rec xs))))))
    (rec xs)))

Автор: VH_ 24.1.2010, 21:20
Хювёнен-Сеппянен "Мир Лиспа" т.1 стр.205:
«Функция является рекурсивной, если в её определении содержится вызов самой этой функции.»

Автор: k0rvin 24.1.2010, 22:17
Цитата(VH_ @ 24.1.2010,  21:20)
Хювёнен-Сеппянен "Мир Лиспа" т.1 стр.205:
«Функция является рекурсивной, если в её определении содержится вызов самой этой функции.»

ну так rec у меня вполне рекурсивна =)

да и книжка мне эта не очень понравилась, "On Lisp" и "PCL" интересней =)

Автор: luser78 24.1.2010, 22:42
Вот правильный код :

Код

(defun REM (x y l)

(COND

((NULL l) nil) 

(   ( EQUAL x (CAR l)) (REM x y (CONS y (CDR l)))  ) 

(   t (CONS (CAR l) (REM x y (CDR l)))   )


)

(setq l '(11 2 2 ))
(setq x 1)
(setq y 7)
(print l)
(print (REM x y l))

Автор: VH_ 25.1.2010, 00:00
>k0rvin
Попробуйте вызвать Вашу функцию (rec) за пределами Вашей функции (replace2). Результат соблаговолите сообщить.
>luser78
Ваша функция (rem) работоспособна, но для каждого элемента исходного списка, равного «новому» значению, выполняет лишний вызов самой себя. И чем больше подходящих для замены элементов, тем больше лишних вызовов. Разработчикам таких функций привет.

Автор: k0rvin 25.1.2010, 00:20
Цитата(VH_ @ 25.1.2010,  00:00)
>k0rvin
Попробуйте вызвать Вашу функцию (rec) за пределами Вашей функции (replace2). Результат соблаговолите сообщить.

я и без запуска могу сказать, что будет =)

только не вижу проблем. функция rec описана рекурсивно? рекурсивно. процесс она порождает рекурсивный? рекурсивный.

зачем же лишние разы передавать переменные, не изменяющиеся от вызова к вызову? лишний расход памяти, лишнее загромождение кода... =)

Автор: VH_ 25.1.2010, 01:11
Да, в принципе я ничего не имею против утверждения, что у Вас проблем никаких не было бы - не Вам же показывать текст преподу и выслушивать его комментарии и оценки.

Автор: adejneka 25.1.2010, 06:33
2k0rvin: в Common Lisp по умолчанию для проверки равенства принято использовать EQL, а не EQ (последняя часто не работает с числами).

Автор: luser78 25.1.2010, 11:55
sw04, бери мой код,, обмозговывай - он работает 100%, там применяется рекурсия.
Если хочешь ещё проверку на новые элементы сделать (чтобы рекрси меньшее кол-во раз выполнялась),
то делай!! А так работает все))) Серьезно!

Автор: VH_ 25.1.2010, 12:57
Уважаемый luser78, сообщение sw04 датируется 8.11.2007.

Автор: k0rvin 25.1.2010, 19:13
Цитата(adejneka @ 25.1.2010,  06:33)
2k0rvin: в Common Lisp по умолчанию для проверки равенства принято использовать EQL, а не EQ (последняя часто не работает с числами).

буду знать. в литературе чаще видел eq, но там правда в основном предполагались символы по-умолчанию =)

Автор: _sg 25.4.2014, 11:32
как вариант:
Код

(defun replace-n-m (w n m &aux (a (car w)))
  (when w (cons (if (equal a n) m a) (replace-n-m (cdr w) n m))))

> (replace-n-m '(1 a 3 a 5 a 7) 'a 'b)
(1 B 3 B 5 B 7)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)