[comp.lang.lisp] substitution in sequences

farquhar@cs.utexas.edu (Adam Farquhar) (08/31/89)

Is there an elegant way to perform substitutions in a sequence where
the new item may be of a different length than the old item?  E.g.

(substitute-it "Common lisp, the Language" "CLtL"
		"The right function does not seem to be in CLtL.")
=>
"The right function does not seem to be in Common Lisp, the Language."

or (substitute-it "abc" "1" "10101") 
=>
 "abc0abc0abc"

Even better would be a function which took a list of (new . old) pairs
and substituted the corresponding NEW for each OLD occuring in the
sequence. 

Thanks,	
	Adam Farquhar.

 

Duchier-Denys@cs.yale.edu (Denys Duchier) (08/31/89)

In article <425@ai.cs.utexas.edu>, farquhar@cs (Adam Farquhar) writes:
> Is there an elegant way to perform substitutions in a sequence where
> the new item may be of a different length than the old item?  E.g.
> 
> (substitute-it "Common lisp, the Language" "CLtL"
> 		"The right function does not seem to be in CLtL.")
> =>
> "The right function does not seem to be in Common Lisp, the Language."
> 
> or (substitute-it "abc" "1" "10101") 
> =>
>  "abc0abc0abc"

How about:

(defun substitute-it (new old seq)
    (let ((i (search old seq)))
      (if (null i) seq
	  (concatenate (type-of seq)
             (subseq seq 0 i)
             new
             (substitute-it new old
                (subseq seq (+ i (length old))))))))

--Denys

chewy@apple.com (Paul Snively) (09/05/89)

In article <425@ai.cs.utexas.edu> farquhar@cs.utexas.edu (Adam Farquhar) 
writes:
> Even better would be a function which took a list of (new . old) pairs
> and substituted the corresponding NEW for each OLD occuring in the
> sequence. 
> 
> Thanks, 
>         Adam Farquhar.

Sounds suspiciously like the SUBLIS function to me!

___________________________________________________________________________
chewy@apple.com
Just because I work for Apple Computer, Inc. doesn't mean that they 
believe what I believe or vice-versa.
___________________________________________________________________________

gupta@prlhp1.prl.philips.co.uk (gupta) (09/12/89)

In article <4022@internal.Apple.COM> chewy@apple.com (Paul Snively) writes:
>In article <425@ai.cs.utexas.edu> farquhar@cs.utexas.edu (Adam Farquhar) 
>writes:
>> Even better would be a function which took a list of (new . old) pairs
>> and substituted the corresponding NEW for each OLD occuring in the
>> sequence. 
>> 
>> Thanks, 
>>         Adam Farquhar.
>
>Sounds suspiciously like the SUBLIS function to me!
>


Ah well, SUBLIS is not flexible enough for Adam's purposes as
it requires its second arg. to be a tree. Adam wanted to operate
on a sequence, which could be a list but could also be a string
or a simple or bit vector. (O.K. - so I'm being pedantic, but
a tree is only a sub-type of a sequence.  Also, Adam wanted the
args in new.old form wheras SUBLIS requires them in old.new form.)

The following does not do any error-handling and does not accept
the first argument in assoc-list form as required, but that's easy to change.

BTW, I extended the contribution made by Denys Duchier in an
earlier posting.

Try this :

(defun subs (new old seq)

  (etypecase seq

	     (simple-string 
	      (let ((i (search old seq)))
		(if (null i) seq
		    (concatenate (type-of seq)
				 (subseq seq 0 i)
				 new
				 (subs new old
				       (subseq seq (+ i (length old))))))))
	     
	     (cons
	      (subst new old seq :test #'equal))
	     
	     ((or (simple-bit-vector) (vector))
	      (let ((new-seq (copy-seq seq)))
		(dotimes (n (length seq) new-seq)
		  (if (eq old (elt new-seq n))
		      (setf (elt new-seq n) new)))))))



(defun substitute-it (&rest args)
  (if (oddp (length args))
      
      (let ((new-old-pairs (butlast args)) 
	    (answer (first (last args)))
	    new-item)
	(declare (special answer))
	
	(loop 
	 (if (setq new-item (pop new-old-pairs))
	     (setq answer (subs new-item
				(pop new-old-pairs)
				answer))
	     (return answer))))))



(defun er (seq)  

  (terpri)
  (dotimes (n (length seq)) 
    (format t "~a " (elt seq n)))
  (values))

 ------------------------------------

> (substitute-it "Common lisp, the Language" "CLtL"
		 "functions"  "function"
		 "do" "does"
		 "appear" "seem"
		"The right function does not seem to be in CLtL.")

"The right functions do not appear to be in Common lisp, the Language."

 ------------------------------------

> (substitute-it 'gobble 'a '(a b c d (a b c (a b (a)))))

(GOBBLE B C D (GOBBLE B C (GOBBLE B (GOBBLE))))

 ------------------------------------

>  (setq sv (make-sequence 'simple-vector 6 :initial-element 'a))
#<Simple-Vector T 6 11AB3AB>

> (setf (elt sv 2) 'b 
	(elt sv 2) 'b)
B

> (er sv)

A A B A B A

>(substitute-it  'as-a-cloud 'a  'i-sailed 'b sv)
#<Simple-Vector T 6 11683AB>

> (er *)

AS-A-CLOUD AS-A-CLOUD I-SAILED AS-A-CLOUD I-SAILED AS-A-CLOUD 

 ------------------------------------

>  (setq sb (make-sequence 'bit-vector 6 :initial-element 0 ))
#<Simple-Bit-Vector 6 1183E93>>  

> (setf (elt sb 2) '1
	(elt sb 4) '1)
1

>(er sb)

0 0 1 0 1 0

> (substitute-it 1 0 0 1 sb)
#<Simple-Bit-Vector 6 1164963>

> (er *)

0 0 0 0 0 0 

 ------------------------------------