您想使用filter
,而不是map
- 因为输出列表的元素可能少于输入列表。所有这些#<void>
返回的值display
都在那里,因为map
将始终在输出列表中包含一个结果,即使对于那些我们不感兴趣的元素也是如此。
(define tbl '(a b c d))
(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)
等效地,并且有点短:
(filter (curry eq? 'c) tbl)
=> '(c)
map
当您想要对输入列表中的每个元素执行某些操作而不丢弃元素时使用。另一方面,filter
用于选择输入列表中的一些元素,那些对#t
给定谓词求值的元素,并且filter
在大多数 Scheme 解释器中都可用,如果它不可用,您可以导入SRFI-1
或使用参考实现。
没有办法只'(c)
使用 using (可以使用plus或等破解它,但这不是想法,是吗?);如果由于某种原因您必须只使用并且不介意返回带有占位符的列表,这里有几个选择: map
map
apply
remove*
map
(map (lambda (item) (if (eq? item 'c) item '%)) tbl) ; placeholder in else part
=> '(% % c %)
(map (lambda (item) (when (eq? item 'c) item)) tbl) ; when has implicit #<void>
=> '(#<void> #<void> c #<void>)
是时候进行一些黑客攻击了。使用map
加号apply
(如@WillNess 的回答中所述),这具有在任何 RxRS 解释器中工作的优势,并且是最便携的解决方案,因为它使用标准程序:
(apply append (map (lambda (item) (if (eq? item 'c) (list item) '())) tbl))
=> '(c)
使用map
加号remove*
:
(remove* (list (void)) (map (lambda (item) (when (eq? item 'c) item)) tbl))
=> '(c)
对于更改,没有map
- 使用的解决方案foldr
:
(foldr (lambda (item a) (append (if (eq? item 'c) (list item) '()) a)) '() tbl)
=> '(c)
当然,你总是可以filter
使用标准过程实现你自己的版本,这也可以在所有 RxRS 解释器之间移植:
(define (filter pred? lst)
(cond ((null? lst)
'())
((not (pred? (car lst)))
(filter pred? (cdr lst)))
(else
(cons (car lst)
(filter pred? (cdr lst))))))
(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)