How to turn a list of string into one string in scheme?
Asked Answered
A

3

12

For example I have (list "a" "1" "b" "2" "c" "3").

Now I want to turn this list into one "a1b2c3".

How do I do that?

Thank you.

Aide answered 2/6, 2013 at 7:6 Comment(0)
I
12

(apply string-append (list "a" "1" "b" "2" "c" "3")) or (string-append* "" (list "a" "1" "b" "2" "c" "3")) should work. See: http://docs.racket-lang.org/reference/strings.html

If you wanted a procedure to do this you can just write (define (strings->string sts) (apply string-append sts))

Irrecoverable answered 2/6, 2013 at 7:35 Comment(2)
This is perfectly fine when you know you will be joining only a small number of strings. More generally, apply-based techniques make an argument list out of their input so they may hit the argument list length limit of the language implementation if they are given a long list. The limit is not very high in some language standards/implementations; not sure what is the situation with Scheme/Racket.Claar
In Racket you don't have this problem, it's safe to use the apply technique, even for long lists.Batista
M
10

Don't reinvent the wheel! in Racket, there exists one procedure specifically for this and its' called string-join:

(string-join '("a" "1" "b" "2" "c" "3") "")
=> "a1b2c3"

Quoting the documentation:

(string-join strs                
             [sep                
              #:before-first before-first                
              #:before-last before-last              
              #:after-last after-last]) → string?

strs : (listof string?)
sep : string? = " "
before-first : string? = ""
before-last : string? = sep
after-last : string? = ""

Appends the strings in strs, inserting sep between each pair of strings in strs. before-last, before-first, and after-last are analogous to the inputs of add-between: they specify an alternate separator between the last two strings, a prefix string, and a suffix string respectively.

Marcheshvan answered 2/6, 2013 at 13:3 Comment(1)
This is also implemented in Guile.Veridical
C
5

For what it's worth, here are some implementations with and without a delimiter (i.e. a string that is inserted between each pair of strings, such as a space or a comma).

The functions fold and fold-right are from SRFI 1.

Using a string port is probably faster when concatenating very many or very long strings. Otherwise there's unlikely to be much speed difference.

Without delimiter argument

Using fold

(define (string-join strings)
  (fold-right string-append "" strings))

Using recursion

(define (string-join strings)
  (let loop ((strings strings) (so-far ""))
    (if (null? strings)
        so-far
        (loop (cdr strings) (string-append so-far (car strings))))))

Using a string port

(define (string-join strings)
  (parameterize ((current-output-port (open-output-string)))
    (for-each write-string strings)
    (get-output-string (current-output-port))))

With a delimiter argument

Using fold

(define (string-join strings delimiter)
  (if (null? strings)
      ""
      (fold (lambda (s so-far) (string-append so-far delimiter s))
            (car strings)
            (cdr strings))))

Using recursion

(define (string-join strings delimiter)
  (if (null? strings)
      ""
      (let loop ((strings (cdr strings)) (so-far (car strings)))
        (if (null? strings)
            so-far
            (loop (cdr strings)
                  (string-append so-far delimiter (car strings)))))))

Using a string port

(define (string-join strings delimiter)
  (if (null? strings)
      ""
      (parameterize ((current-output-port (open-output-string)))
        (write-string (car strings))
        (for-each (lambda (s)
                    (write-string delimiter)
                    (write-string s))
                  (cdr strings))
        (get-output-string (current-output-port)))))
Claar answered 18/4, 2019 at 8:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.