2012-01-12 15 views
20

Quiero convertir ("USERID=XYZ" "USERPWD=123") en "USERID=XYZ&USERPWD=123". Probé¿Cuál es la forma canónica de unir cadenas en una lista?

(apply #'concatenate 'string '("USERID=XYZ" "USERPWD=123")) 

que devolverá ""USERID=XYZUSERPWD=123".

Pero no sé cómo insertar '&'? La siguiente función funciona pero parece un poco complicada.

(defun join (list &optional (delim "&")) 
    (with-output-to-string (s) 
     (when list 
      (format s "~A" (first list)) 
      (dolist (element (rest list)) 
       (format s "~A~A" delim element))))) 

Respuesta

37

Uso FORMAT.

~{ y ~} iteración designan, ~A denota la impresión estética, y ~^ (también conocido como Tilde circunfleja en la documentación) denota la impresión, sólo cuando algo le sigue.

* (format nil "~{~A~^, ~}" '(1 2 3 4)) 

"1, 2, 3, 4" 
* 
+0

no sabía nada de ~ ^; ¡bonito! –

+0

Desafortunadamente, esto no funciona en Emacs "elisp". Tienen una función de formato diferente. ¿Hay alguna manera comparable de hacer esto en Emacs? – killdash9

+0

@russ: Probablemente. Al no ser un asistente de elisp, volví a Lisp básico ... '(defun join-to-str (cadenas cosa y resto) (etiquetas ((recurser (cadenas) (cond ((> (longitud de cadenas) 1) (append (lista (cadenas de automóviles) cosa) (recurser (cadenas CDR)))) (t (cons (cadenas de automóviles) nil))))) (aplicar 'concat (cadenas recurser)))) ' –

1

Suponiendo una lista de cadenas y un único delimitador de caracteres, lo siguiente debe funcionar de manera eficiente para la invocación frecuente en las listas cortas:

(defun join (list &optional (delimiter #\&)) 
    (with-output-to-string (stream) 
    (join-to-stream stream list delimiter))) 

(defun join-to-stream (stream list &optional (delimiter #\&)) 
    (destructuring-bind (&optional first &rest rest) list 
    (when first 
     (write-string first stream) 
     (when rest 
     (write-char delimiter stream) 
     (join-to-stream stream rest delimiter))))) 
0

Un poco tarde a la fiesta, pero reduce funciona bien:

(reduce (lambda (acc x) 
      (if (zerop (length acc)) 
       x 
       (concatenate 'string acc "&" x))) 
     (list "name=slappy" "friends=none" "eats=dogpoo") 
     :initial-value "") 
0
(defun %d (stream &rest args) 
    (declare (ignore args) 
      (special delim)) 
    (princ delim stream)) 

(defun join (list delim) 
    (declare (special delim)) 
    (format nil "~{~a~^~/%d/~:*~}" list)) 
Cuestiones relacionadas