2016-07-13 2 views
0

に追加されていません。なぜリストは次のように私は小さなテキストファイルを持っているラケット

one, 50, 40, 65, 500 
two, 80, 70, 100, 250 
three, 100, 55, 125, 100 
four, 50, 45, 58, 850 

私はそれを読むために、各ラインの第二列のすべての値のリストを作成しようとしています。

#lang racket 
(define (testfn fname) 
(let ((sl '()) (list2 (list)) (templist '()) (ss "")) 
    (set! sl (file->lines fname)) 
    (for ((line sl)) 
     (set! templist (string-split line ",")) 
     (println templist) 
     (set! ss (list-ref templist 1)) 
     (println ss) 
     (append list2 ss)  ; does not work 
     (append list2 (list ss)) ; does not work 
     (cons ss list2)   ; does not work 
     (cons (list ss) list2) ; does not work 
     (cons list2 (list ss)) ; does not work 
     (cons list2 ss)   ; does not work 
     (println list2) 
) 
    (println list2))) 

(testfn "test.txt") 

しかし、「リスト2」は、私が上記の使用している多くの方法のいずれかと、文字列「SS」で追加取得されていません:以下の私が使用していたコードです。出力には次のように表示されます。

'("one" " 50" " 40" " 65" " 500") 
" 50" 
'() 
'("two" " 80" " 70" " 100" " 250") 
" 80" 
'() 
'("three" " 100" " 55" " 125" " 100") 
" 100" 
'() 
'("four" " 50" " 45" " 58" " 850") 
" 50" 
'() 
'() 
> 

問題はどこにありますか?どのように解決できますか?

編集:間違いを修正することは@JohnClementsによって指摘された後、次のコードは動作します:

#lang racket 
(define (testfn fname) 
(let ((sl '()) (list2 (list)) (templist '()) (ss "")) 
    (set! sl (file->lines fname)) 
    (for ((line sl)) 
     (set! templist (string-split line ",")) 
     (set! ss (list-ref templist 1)) 
     (set! list2 (append list2 (list ss))) 
     (println list2) 
) 
    (println list2))) 

(testfn "test.txt") 

出力:

'(" 50") 
'(" 50" " 80") 
'(" 50" " 80" " 100") 
'(" 50" " 80" " 100" " 50") 
'(" 50" " 80" " 100" " 50") 
> 

答えて

3

む〜!あなたのコードは非常に命令的なスタイルで書かれています。このスタイルのコードは読んだり維持したりするのが難しいです。コードをはるかに小さな関数に分割し、How To Designプログラムの設計レシピ(www.htdp.org)に従ってコードを開発すれば、よりクリーンなものを手に入れることができます。

実行している基本的な問題の1つは、「追加」などの機能が突然変異を引き起こすという前提です。具体的には、たとえば(append a b)などを呼び出すと、呼び出し後にこれらのリストの一方または両方が異なると仮定しています。これはそうではありません。このコードを実行した後、

#lang racket 

(define a 3) 
(define b 6) 
(+ a b) 
(- b a) 
(+ (* 2 a) b) 

abの値が何を次のようになります、私はこのコードを書いた想像なぜ

表示するには?

あなたはおそらくそれらがまだ3と6であると思うでしょう。それは、追加の と減算が引数を変更しないためです。同じ事はconsappendの真です。したがって、(append a b)を呼び出すと新しいリストが生成されますが、その値を使用しないとどこにも移動しません。ここで

、...非常に迅速に、私はあなたのためにいくつかのコードを書く

EDITしてみましょう。ここではHTDPスタイルを使用して、各リストの2番目の要素を返すプログラムです

を:

#lang racket 

(require rackunit) 

;; given a list of lists, return the second of each list: 
;; list-of-lists -> list 
(define (second-element-map lol) 
    (cond [(empty? lol) empty] 
     [else (cons (second (first lol)) 
        (second-element-map (rest lol)))])) 

;; let's test it: 
(check-equal? (second-element-map '((a b c) (d e f g) (1 2 3))) 
       '(b e 2)) 

;; given a list of lines, split each one into commas 
(define (split-each-line lines) 
    (cond [(empty? lines) empty] 
     [else (cons (string-split (first lines) ",") 
        (split-each-line (rest lines)))])) 

;; let's test it: 
(check-equal? (split-each-line '("a,34,2987" "hn th, th")) 
       '(("a" "34" "2987") 
       ("hn th" " th"))) 

;; given a filename, return a list containing the second element of 
;; each list 
;; path-string -> list 
(define (testfn fname) 
    (second-element-map (split-each-line (file->lines fname)))) 

(testfn "/tmp/abc.txt") 

短くすることはできますか?もちろん。 HtDPスタイルはきれいで、動作することが保証されています。

...しかし、ここでは、私は個人消費のためにこのプログラムを書きたい方法は次のとおりです。

#lang racket 
(define (testfn2 fname) 
    (for/list ([l (in-list (file->lines fname))]) 
    (second (string-split l ",")))) 

(testfn2 "/tmp/abc.txt") 
+0

はい、私はそれを得ました。 (set!list2(append list2(list ss)))が働いていました。ありがとう。 – rnso

+1

2番目(短い方)のプログラムがどのように機能しているかを説明できるとすばらしいことでしょう。 – rnso

+0

このプログラムはこう言っています:testfn2は関数で、引数は 'fname'です。あなたがそれを呼び出すと、ファイル内のすべての行を考慮し、その行をコンマで区切った結果の2番目のものを取って得られた結果のリストを作成します。 –

関連する問題