[racket] String manipulation without regex opinion

From: Ryan Culpepper (ryan at cs.utah.edu)
Date: Tue Nov 6 15:32:14 EST 2012

On 11/06/2012 03:23 PM, Ryan Culpepper wrote:
> On 11/06/2012 02:59 PM, Grant Rettke wrote:
>> Hi,
>>
>> Usually there are homework problems and stuff for tweaking strings but I
>> was just playing around for the fun of it. I wondered what is the "best
>> way" to do a couple of simple tasks but without regex. Here are two of
>> them. They are not optimized I just wrote them in a way that seemed the
>> simplest. What is a better way or different way?
>>
>> #lang racket
>>
>> (require rackunit)
>>
>> ;; string -> string
>> ;; Removes vowels from the input
>> (define remove-vowels
>>    (lambda (word)
>>      (let ((test (lambda (c) (not (member c (list #\a #\e #\i #\o
>> #\u)))))
>>            (ls (string->list word)))
>>        (list->string (filter test ls)))))
>
> Here's one alternative that should allocate half as many intermediate
> pairs (by switching from string->list and filter to in-string and
> #:unless):

I take that back; for/list accumulates and reverses its result, so it 
creates almost as many pairs as your version does.

Whoops,
Ryan

> (define (remove-vowels s)
>    (list->string
>     (for/list ([c (in-string s)]
>                #:unless (memv c '(#\a #\e #\i #\o #\u)))
>       c)))
>
> If I were really worried about performance, I would allocate a new
> string the size of the old string and copy characters from old to new,
> skipping vowels, and take the appropriate substring at the end. I might
> also delay the allocation of the copy until I found the first vowel; if
> there are no values, then the function can just return the string itself
> (unless the function needs to return a fresh string because of mutation
> elsewhere in the program).
>
>> (check-equal? (remove-vowels "") "")
>> (check-equal? (remove-vowels "f") "f")
>> (check-equal? (remove-vowels "a e i o u") "    ")
>>
>> ;; string -> string
>> ;; Replaces spaces in the input with dashes
>> (define replace-spaces
>>   (lambda (word)
>>     (let ((test (lambda (c) (if (equal? c #\space) #\- c)))
>>           (ls (string->list word)))
>>       (list->string (map test ls)))))
>>
>> (check-equal? (replace-spaces "") "")
>> (check-equal? (replace-spaces " ") "-")
>> (check-equal? (replace-spaces "a b c") "a-b-c")
>
> Similar, except here you wouldn't have to worry about resizing the copy
> at the end.
>
> Ryan
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users


Posted on the users mailing list.