Scheme 如何从过滤器映射中仅获取一个解决方案?

Scheme 如何从过滤器映射中仅获取一个解决方案?,scheme,Scheme,在scheme中,我有两个列表list1和list2,如果list1的任何元素等于z,我想返回对应于list2元素的值。我只知道列表1上的一个元素等于z 我的代码正在工作,但我得到的结果是”(bla),但我只想得到bla的结果。如何删除这个括号?最简单的方法是对结果调用car,因为car返回列表的第一个元素。但如果没有匹配的元素,则会导致错误-您的函数将返回一个空列表,car将失败 一些语言(如Haskell)实现了一个。选项类型为空或仅包含一个值。它在某种程度上类似于一个不能包含多个值的列表。

在scheme中,我有两个列表
list1
list2
,如果
list1
的任何元素等于z,我想返回对应于
list2
元素的值。我只知道列表1上的一个元素等于z


我的代码正在工作,但我得到的结果是
”(bla)
,但我只想得到
bla
的结果。如何删除这个括号?

最简单的方法是对结果调用
car
,因为
car
返回列表的第一个元素。但如果没有匹配的元素,则会导致错误-您的函数将返回一个空列表,
car
将失败

一些语言(如Haskell)实现了一个。选项类型为空或仅包含一个值。它在某种程度上类似于一个不能包含多个值的列表。您可以为scheme实现一个,并将其用作返回类型


另一种方法是返回列表的第一个元素,如果没有找到结果,则返回
#f
(false)。这种方法基于这样一个事实,即
Scheme
是一种动态语言。

您可以使用
car
检索输出列表中的第一个元素,但我不认为
filter map
是这里的最佳选择-毕竟您对
filter map
返回的结果列表不感兴趣,仅在单个元素中—这是不可避免的,即使列表为空,也会返回列表。基本上,您需要在关联列表中查找值。请尝试以下方法:

(filter-map (lambda (x y) (and (eq? x z)   y) ) list1 list2 ) 
说明:

  • (map cons list1 list2)
    构建一个关联列表,其中
    list1
    中的元素是键,
    list2
    中的元素是值
  • assq
    查找具有
    'z
    作为其键的键值对(使用
    eq?
    进行比较),并返回该对
  • cdr
    返回该对的值部分
或者,您可以检查解释器是否有可用的哈希表实现(如果您必须高效地执行多个搜索,则很有用),例如在Racket中:

(cdr (assq 'z (map cons list1 list2)))
=> 'bla
说明:

  • (map cons list1 list2)
    构建一个关联列表,其中
    list1
    中的元素是键,
    list2
    中的元素是值
  • make hasheq
    使用关联列表创建一个新的哈希表,并在查找给定键的值时使用
    eq?
  • hash ref
    返回与键
    'z
请注意,如果键不在
列表1
中,当我们试图获取值时,上述两个选项都会引发错误,您必须决定在需要时如何处理这种情况;例如,我们可以返回
#f


虽然
filter-map
很好而且功能强大,但迭代回答可能是更直接的方法(阅读:可理解)

(let ((pair (assq 'z (map cons list1 list2))))
  (and pair (cdr pair)))

(hash-ref (make-hasheq (map cons list1 list2)) 'z
          (const #f))

assoc
不会引发错误如果找不到密钥,它将返回
#f
。另外,对于
hash ref
,您可以传入一个过程,如果找不到键,则调用该过程;只是默认过程引发了一个错误。@ChrisJester Young我没有说清楚,我的意思是
cdr
hash ref
在尝试获取值时都会引发错误。我重新表述了上面的部分,并添加了您的建议;)<代码>(和配对(cdr配对)),或者使用
(cond((assoc…=>cdr)…)
:-D@ChrisJester-杨明白了。最重要的是优雅!伟大的此外,由于OP使用的是
eq?
,因此您可以切实使用
assq
make hasheq
(假设Racket的哈希接口)。
(let ((pair (assq 'z (map cons list1 list2))))
  (and pair (cdr pair)))

(hash-ref (make-hasheq (map cons list1 list2)) 'z
          (const #f))
#lang racket
(define list1 '(a b z d))
(define list1a '(a b c d)) ; doesn't have 'z in it
(define list2 '(1 2 3 4))
(define (find-matching-pair lst1 lst2)
  (let loop ((l1 lst1)
             (l2 lst2))
    (cond ((null? l1) #f) ; didn't find it
          ((eqv? (car l1) 'z) (car l2)) ; this ASSUMES l2 is not shorter than l1
          (else (loop (cdr l1) (cdr l2))))))
(find-matching-pair list1 list2) ; => 3
(find-matching-pair list1a list2) ; => #f