使用 for/fold 检查嵌套列表中是否存在元素的正确方法是什么;Racket?
What is the correct way to use for/fold check if an element exists in nested list ;Racket?
所以,我正在尝试编写一个函数,它接受两个参数,一个嵌套的数字 L 列表和一个数字 n。这
函数 return 如果数字 n 属于任何列表,则为真,否则为假。
例如,(sob35 '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8) returns true 和 (sob35 '((1 2 3) (5 4) ( 6 7) (8 9
10 11)) 22) return 错误。
我用 rest 的成员函数测试了这个,看它是否会检查 6 是否是嵌套列表的成员,
(member 6 ((rest '((1 2 3) (5 4) (6 7) (8 9 10 11))))) it returned
application: not a procedure;
expected a procedure that can be applied to arguments
given: '((5 4) (6 7) (8 9 10 11)) what i had given it was indeed a list
(define sob35
(lambda ( l1 l2 )
(for/list ([ L l1 ] [ N l2 ])
(if ( member N (rest (L))) "True" "False"))))
我认为我的想法不正确,因为我认为如果 N 是 L 的成员,它应该 return true 否则它应该 return false,虽然当我 运行 它
(sob35 '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
. . application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 2 3)
我不明白应用程序错误是在暗示什么;它应该包含一个列表
在 List of Lists
输入上使用 for/or
,以实现所需...
(define two-sequences
(lambda (l1 l2)
(for/or ([N l1])
(and (member l2 N) #t))))
测试
racket@> (define two-sequences (lambda (l1 l2) (for/or ([N l1]) (and (member l2 N) #t))))
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 6)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 16)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 10)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 3)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 12)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 1)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 2)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 3)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 4)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 5)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 6)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 7)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 9)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 10)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 11)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 12)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 13)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 14)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 15)
#f
racket@>
这个怎么样...
(member 6 (rest '((1 2 3) (5 4) (6 7) (8 9 10 11))))
在原来的调用中,就像...
(member 6 ( (rest '((1 2 3) (5 4) (6 7) (8 9 10 11))) ))
;;^ ;; ^
在评估 (rest ...)
之后得到 function application
的处理。
(let ((result-of-evaluation-of-rest (rest '((1 2 3) (5 4) (6 7) (8 9 10 11)))))
(member 6 (result-of-evaluation-of-rest)))
其中 result-of-evaluation-of-rest
不是一个函数,而是一个列表。而我们真正想要的是...
(let ((result-of-evaluation-of-rest (rest '((1 2 3) (5 4) (6 7) (8 9 10 11)))))
(member 6 result-of-evaluation-of-rest))
您需要一个以嵌套方式工作的 member
函数。
在 lisp 传统中,它将被称为 member*
- 因为它是 member
的递归工作形式(用于平面列表)。
(define (member*? nested-list element (test equal?))
(cond ((null? nested-list) #f)
((list? (car nested-list)) (or (member*? (car nested-list) element test)
(member*? (cdr nested-list) element test)))
((test (car nested-list) element) #t)
(else (member*? (cdr nested-list) element test))))
因为嵌套可以任意深但递归不是,
可以使用 tail-recursive 函数。
(define (member*? nested-list element (test equal?) (acc #f))
(cond ((null? nested-list) acc)
((list? (car nested-list)) (member*? (cdr nested-list) element test
(or acc (member*? (car nested-list) element test))))
((test (car nested-list) element) #t)
(else (member*? (cdr nested-list) element test acc))))
一个简单的“for 循环”答案可能特定于“列表列表”参数。
问题中引用的 Racket 的 for/fold
可以使用:
(define (member-of-sub-list? lols x)
(for/fold ([result #f])
([ls lols])
(or result (not (not (member x ls))))))
;(member-of-sub-list? '((1) (2 3 4)) 3) => #t
;(member-of-sub-list? '((1) (2 3 4)) 99) => #f
但是,当学习Scheme或Racket时,系统地开发这样的功能是有帮助的。
首先,编写一个 stub 函数,带有 signature 和 purpose,以及 simple tests:
(define (member-of-sub-list? lolox x) ;; (ListOf ListOfX) X -> Boolean
;; produce whether x occurs in sub-lists of lolox
#f)
(check-expect (member-of-sub-list? '(()) 0) #f)
(check-expect (member-of-sub-list? '((0)) 0) #t)
然后使用示例和
standard template
填写函数,测试:
(define (member-of-sub-list? lolox x) ;; (ListOf ListOfX) X -> Boolean
;; produce whether x occurs in sub-lists of lolox
(cond
[(empty? lolox) #f ]
[(member x (first lolox)) #t ]
[else (member-of-sub-list? (rest lolox) x) ]))
(check-expect (member-of-sub-list? '((1) (2 3 4) ()) 0) #f)
(check-expect (member-of-sub-list? '((1) (2 0 4) ()) 0) #t)
(编写此解决方案比阅读和理解 for/fold
文档花费的时间更少)
所以,我正在尝试编写一个函数,它接受两个参数,一个嵌套的数字 L 列表和一个数字 n。这
函数 return 如果数字 n 属于任何列表,则为真,否则为假。
例如,(sob35 '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8) returns true 和 (sob35 '((1 2 3) (5 4) ( 6 7) (8 9
10 11)) 22) return 错误。
我用 rest 的成员函数测试了这个,看它是否会检查 6 是否是嵌套列表的成员,
(member 6 ((rest '((1 2 3) (5 4) (6 7) (8 9 10 11))))) it returned
application: not a procedure;
expected a procedure that can be applied to arguments
given: '((5 4) (6 7) (8 9 10 11)) what i had given it was indeed a list
(define sob35
(lambda ( l1 l2 )
(for/list ([ L l1 ] [ N l2 ])
(if ( member N (rest (L))) "True" "False"))))
我认为我的想法不正确,因为我认为如果 N 是 L 的成员,它应该 return true 否则它应该 return false,虽然当我 运行 它
(sob35 '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
. . application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 2 3)
我不明白应用程序错误是在暗示什么;它应该包含一个列表
在 List of Lists
输入上使用 for/or
,以实现所需...
(define two-sequences
(lambda (l1 l2)
(for/or ([N l1])
(and (member l2 N) #t))))
测试
racket@> (define two-sequences (lambda (l1 l2) (for/or ([N l1]) (and (member l2 N) #t))))
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 6)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 16)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 10)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 3)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 12)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 1)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 2)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 3)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 4)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 5)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 6)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 7)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 8)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 9)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 10)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 11)
#t
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 12)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 13)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 14)
#f
racket@> (two-sequences '((1 2 3) (5 4) (6 7) (8 9 10 11)) 15)
#f
racket@>
这个怎么样...
(member 6 (rest '((1 2 3) (5 4) (6 7) (8 9 10 11))))
在原来的调用中,就像...
(member 6 ( (rest '((1 2 3) (5 4) (6 7) (8 9 10 11))) ))
;;^ ;; ^
在评估 (rest ...)
之后得到 function application
的处理。
(let ((result-of-evaluation-of-rest (rest '((1 2 3) (5 4) (6 7) (8 9 10 11)))))
(member 6 (result-of-evaluation-of-rest)))
其中 result-of-evaluation-of-rest
不是一个函数,而是一个列表。而我们真正想要的是...
(let ((result-of-evaluation-of-rest (rest '((1 2 3) (5 4) (6 7) (8 9 10 11)))))
(member 6 result-of-evaluation-of-rest))
您需要一个以嵌套方式工作的 member
函数。
在 lisp 传统中,它将被称为 member*
- 因为它是 member
的递归工作形式(用于平面列表)。
(define (member*? nested-list element (test equal?))
(cond ((null? nested-list) #f)
((list? (car nested-list)) (or (member*? (car nested-list) element test)
(member*? (cdr nested-list) element test)))
((test (car nested-list) element) #t)
(else (member*? (cdr nested-list) element test))))
因为嵌套可以任意深但递归不是, 可以使用 tail-recursive 函数。
(define (member*? nested-list element (test equal?) (acc #f))
(cond ((null? nested-list) acc)
((list? (car nested-list)) (member*? (cdr nested-list) element test
(or acc (member*? (car nested-list) element test))))
((test (car nested-list) element) #t)
(else (member*? (cdr nested-list) element test acc))))
一个简单的“for 循环”答案可能特定于“列表列表”参数。
问题中引用的 Racket 的 for/fold
可以使用:
(define (member-of-sub-list? lols x)
(for/fold ([result #f])
([ls lols])
(or result (not (not (member x ls))))))
;(member-of-sub-list? '((1) (2 3 4)) 3) => #t
;(member-of-sub-list? '((1) (2 3 4)) 99) => #f
但是,当学习Scheme或Racket时,系统地开发这样的功能是有帮助的。
首先,编写一个 stub 函数,带有 signature 和 purpose,以及 simple tests:
(define (member-of-sub-list? lolox x) ;; (ListOf ListOfX) X -> Boolean
;; produce whether x occurs in sub-lists of lolox
#f)
(check-expect (member-of-sub-list? '(()) 0) #f)
(check-expect (member-of-sub-list? '((0)) 0) #t)
然后使用示例和 standard template 填写函数,测试:
(define (member-of-sub-list? lolox x) ;; (ListOf ListOfX) X -> Boolean
;; produce whether x occurs in sub-lists of lolox
(cond
[(empty? lolox) #f ]
[(member x (first lolox)) #t ]
[else (member-of-sub-list? (rest lolox) x) ]))
(check-expect (member-of-sub-list? '((1) (2 3 4) ()) 0) #f)
(check-expect (member-of-sub-list? '((1) (2 0 4) ()) 0) #t)
(编写此解决方案比阅读和理解 for/fold
文档花费的时间更少)