From: Adam White on
On 01/30/2010 03:06 AM, Richard Fateman wrote:


> (defun f(l)
> (cond ((and(stringp (car l))(stringp (cadr l)))
> (f (cons (concatenate 'string (car l) (cadr l))
> (cddr l))))
> ((cadr l) (cons (car l)(f (cdr l))))
> (t l)))
>
> ;; (f '("1" "2" 3 4 "5" "6" 7 8 "9")) --> ("12" 3 4 "56" 7 8 "9")

Thanks Richard - that's exactly the sort of thing I had in mind but
couldn't express.

A
From: Pillsy on
On Jan 29, 4:15 pm, Kaz Kylheku <kkylh...(a)gmail.com> wrote:

> Raymond Wiker wrote:

> > "Frode V. Fjeld" <fr...(a)netfonds.no> writes:
[...]
> Users of CL (COBOL-LISP) would be helpless without loop.

You mean helpless the same way you are, writing programs O(N^2)
behavior due to repeatedly using string-append?

> Scheme:

> (define (fuse in out)
>   (if (null? in)   (reverse out)
>     (let ((x (car in)))
>       (fuse (cdr in)
>         (if (and (string? x) (pair? out) (string? (car out)))
>           (cons (string-append (car out) x) (cdr out))
>           (cons x out))))))

Sheesh,
Pillsy
From: Huai Yuan on
Adam White <spudboy(a)iinet.net.au> writes:
> Given a mixed list of strings and other items, I'd like to concatenate
> all strings (and only strings) adjacent to each other.
>
> So for '("1" "2" 3 4 "5" "6" 7 8 "9"), we should return
>
> ("12" 3 4 "56" 7 8 "9")
[...]

(defun concatenate-adjacent-strings (list)
(reduce (lambda (x y)
(if (and (stringp x) (stringp (car y)))
(cons (concatenate 'string x (car y)) (cdr y))
(cons x y)))
list :from-end t :initial-value nil))
From: Ole Arndt on
Richard Fateman <fateman(a)cs.berkeley.edu> writes:

> (defun f(lis)
> (let ((h (first lis))(r (rest lis)))
> (cond ((and(stringp h)(stringp (first r)))
> (f (cons (concatenate 'string h (first r))
> (rest r))))
> (r (cons h (f r)))
> (t lis))))

Much nicer, but not tail recursive anymore ;)

Ole
--
Ole Arndt http://www.sugarshark.com
From: Tayssir John Gabbour on
Hi,

On Jan 29, 8:06 pm, Richard Fateman <fate...(a)cs.berkeley.edu> wrote:
> (defun f(l)
> (cond ((and(stringp (car l))(stringp (cadr l)))
> (f (cons (concatenate 'string (car l) (cadr l))
> (cddr l))))
> ((cadr l) (cons (car l)(f (cdr l))))
> (t l)))

If I understand correctly, there's a bug -- CADR will have a problem
with nil. Instead, CDDR should be used, otherwise this happens:

cl-user> (f '(1 nil "2" "3" "4" "5"))
(1 NIL "2" "3" "4" "5")


This computer I'm on don't have Slime+SBCL, so excuse me for the
Clojure version -- this is trivially translatable to idiomatic CL:


(defn vec-butlast [a-vector]
(subvec a-vector 0 (max 0 (dec (count a-vector)))))

(defn concatenate-adjacent-strings [lst]
(reduce (fn [accumulator item]
(if (and (string? (last accumulator))
(string? item))
(conj (into [] (vec-butlast accumulator))
(str (last accumulator) item))
(conj accumulator item)))
[]
lst))


People elsewhere on this thread are attempting to buffer the strings
to avoid worst-case repeated string concatenation, so here's an
optimized version:

(defn concatenate-adjacent-strings-2 [lst]
(let [[result buffer]
(reduce (fn [[accumulator buffer] item]
(cond (string? item)
[accumulator (conj buffer item)]
(seq buffer)
[(conj accumulator (apply str buffer) item)
[]]
:else
[(conj accumulator item) buffer]))
[[] []]
lst)
result (if (seq buffer)
(conj result (apply str buffer))
result)]
result))


While I'm a big LOOP partisan, I think REDUCE is just more
streamlined, perhaps clearer than LOOP. I agree with Kaz that pattern-
matching would be great, if there were an available library.


All the best,
Tayssir