Find empy lines in text file

272 views Asked by At

I've been learning racket for a few days and I'm puzzled with this task, I'm trying to find empty lines in a text file and select a random empty line to INSERT the text "calculation here", this is as far as I have gotten so far.

for example: myfile.txt has the contents:

line1

line2
line3

line4

after the script is run, myfile.txt should now look like:

line1
calculation here
line2
line3

line4

or:

line1

line2
line3
calculation here
line4

un-working code below:

#lang racket

(define (write-to-file host text) (
             with-output-to-file host (                 
             lambda () (
             write text))
             #:exists 'replace))

(define empty-lines '()) ;store line number of empty line (if any)

(define (file-lines text-file) 
                (file->lines text-file))

(define (add-to-list line-num)
  (set! empty-lines (cons line-num empty-lines)))

(let loop ((l (file-lines "myfile.txt")))
   (cond ((null? l) #f)
         (else
           (printf "~s\n" (first l)) ; just for debugging
           (cond ((equal? (first l) "") (add-to-list (first l)))(else #f))
           (loop (rest l)))))

;now i need to select a random line from the list of empty-lines.
;and write "calculations here" to that line

there's no problem with the read lines method i am using, the problem is detecting and selecting a random empty space to insert my text.

3

There are 3 answers

2
Greg Hendershott On BEST ANSWER

Given a file name, you can read it into a list of lines using file->lines. So for instance:

(for ([line (in-list (file->lines "some-file"))])
  (displayln (cond [(zero? (string-length line)) (make-random-line)]
                   [else line])))

Where make-random-line is some function you define to return a random string, as you said you wanted to do.

The above reads the entire file into a list in memory. For larger files, it would be better to process things line by line. You can do this using the in-lines sequence:

(with-input-from-file "some-file"
  (thunk
   (for ([line (in-lines)])
     (displayln (cond [(zero? (string-length line)) (make-random-line)]
                      [else line])))))

Update

Now that I understand your question:

#lang racket

(define lines (file->lines "some-file-name"))

(define empty-line-numbers (for/list ([line (in-list lines)]
                                      [n    (in-naturals)]
                                      #:when (zero? (string-length line)))
                             n))

(define random-line-number (list-ref empty-line-numbers
                                     (random (length empty-line-numbers))))

(for ([line (in-list lines)]
      [n    (in-naturals)])
  (displayln (cond [(= n random-line-number) "SOME NEW STRING"]
                   [else line])))
3
Vatsalya On

look for 2 concurrent \n in the file. I am pretty sure there is a way in racket to do that. store those indices in a list select a pair randomly and replace the second \n with "calculation here\n".

0
Vatsalya On
(define (read-next-line-iter file)
       (let ((line (read-line file)))
         (unless (eof-object? line)
           (display line)
           (newline)
           (read-next-line-iter file))))
(call-with-input-file "foobar.txt" read-next-line-iter)

http://rosettacode.org/wiki/Read_a_file_line_by_line#Racket

this function can help you read a file line by line. check if the length is 0. and replace that line with the comment