为什么列表没有附加在球拍中
Why list is not appending in Racket
我有一个如下的小文本文件:
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")
但是,'list2' 没有附加字符串 '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")
>
哎呀!您的代码是以非常命令式的风格编写的。这种风格的代码很难阅读和维护。我想您会发现,如果您将代码分解成更小的函数,并根据如何设计程序设计秘诀 (www.htdp.org) 开发代码,您会得到更简洁的代码。
您 运行 遇到的一个基本问题是假设 "append" 等函数会导致突变。具体来说,您假设如果您调用 (append a b)
,则这些列表中的一个或两个在调用后会有所不同。不是这种情况。
想知道为什么,想象一下我写了这段代码:
#lang racket
(define a 3)
(define b 6)
(+ a b)
(- b a)
(+ (* 2 a) b)
在 运行 这段代码之后,a
和 b
的值是多少?
我想你可能希望它们仍然是 3 和 6。那是因为加法
和减法不会改变他们的论点。 cons
也是一样
和 append
。因此调用 (append a b)
会生成一个新列表,但如果您不使用该值,则它不会去任何地方。
在这里,让我很快地为您编写一些代码...
编辑:
这是一个 returns 每个列表的第二个元素的程序,使用 HtDP 样式:
#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")
我有一个如下的小文本文件:
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")
但是,'list2' 没有附加字符串 '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")
>
哎呀!您的代码是以非常命令式的风格编写的。这种风格的代码很难阅读和维护。我想您会发现,如果您将代码分解成更小的函数,并根据如何设计程序设计秘诀 (www.htdp.org) 开发代码,您会得到更简洁的代码。
您 运行 遇到的一个基本问题是假设 "append" 等函数会导致突变。具体来说,您假设如果您调用 (append a b)
,则这些列表中的一个或两个在调用后会有所不同。不是这种情况。
想知道为什么,想象一下我写了这段代码:
#lang racket
(define a 3)
(define b 6)
(+ a b)
(- b a)
(+ (* 2 a) b)
在 运行 这段代码之后,a
和 b
的值是多少?
我想你可能希望它们仍然是 3 和 6。那是因为加法
和减法不会改变他们的论点。 cons
也是一样
和 append
。因此调用 (append a b)
会生成一个新列表,但如果您不使用该值,则它不会去任何地方。
在这里,让我很快地为您编写一些代码...
编辑:
这是一个 returns 每个列表的第二个元素的程序,使用 HtDP 样式:
#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")