【问题标题】:Need help searching in a list in Racket需要帮助在 Racket 的列表中搜索
【发布时间】:2017-03-30 07:15:04
【问题描述】:

我为find-index写了以下函数:

(: finind : (Listof Integer) Integer -> (Option Integer))
;; helper function for find-index
(define (finind a b)
   (let loop ((a a) (c 0))
      (cond 
         ((empty? a) 'None)
         ((equal? (first a) b) (Some c))
         (else (loop (rest a) (add1 c))))))

(: find-index : (Integer -> Boolean) (Listof Integer) 
                 -> (Option (Pr (Option Integer) Integer)))
;; return the first item to pass the test, if there is one,
;; along with its (0-based) index
(define (find-index f x)
   (match x
      ('() 'None)
      ((cons hd '())
         (if (f hd) (Some (Pr (finind x hd) hd)) 'None)) 
      ((cons hd tl)
         (if (f hd) (Some (Pr (finind x hd) hd)) 
                    (find-index f tl)))))

现在,finind 可以单独使用,但是当我将它与find-index 一起使用时,它只会返回(Some 0)

(finind (list 45 41 9) 9) 的结果是 (Some 2)

但是,(find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 9)) 的结果是 (Some (Pr (Some 0) 9)),即使它应该是 (Some (Pr (Some 2) 9))

所以我知道它可能会发生,因为我有 (finind x hd) 来显示我的索引,并且因为它的 hd 它不会改变。但是我该如何解决呢?我一直在尝试,但徒劳无功。有人可以帮忙吗?谢谢!

【问题讨论】:

  • 在最后一个条件下,当谓词为假时,您将递归到find-index,并且您没有以任何方式传递索引偏移量,因此它无法知道这是您第三次这样做.也许用索引包装并使用它可以解决您的问题。
  • 我不明白。能举个例子吗?
  • 你没有将'(45 41 9)传递给finind,你传递的是第一个头部满足f的尾巴,即'(9)
  • 您能否在代码中反映正确的做法?我知道问题所在,但现在如何更改代码以使其正常工作:(
  • @NishantAggarwal 当您通过测试函数 f'(41 9) 时,结果将是 (find-index f (cdr '(41 9))),它会找到它,但 find-index 的实例不知道它正在查看第二个索引,而不是第一个。它会寻找我,因为您也想将函数传递给助手并让 find-index 只需调用 findind 或者您可以将助手移动到 find-index 以便您可以访问 f

标签: functional-programming scheme racket typed-racket


【解决方案1】:

您可以使用functional-lib 包来简化此操作

(require data/maybe)    

(define (find f xs)
  (cond ((empty? xs) nothing)
        ((f (car xs)) (just (car xs)))
        (else (find f (cdr xs)))))

(define (find-index f xs (i 0))
  (cond ((empty? xs) nothing)
        ((f (car xs)) (just i))
        (else (find-index f (cdr xs) (add1 i)))))

(find (λ (x) (< x 10)) '(10 11 3 2 1))       ;; (just 3)
(find-index (λ (x) (< x 10)) '(10 11 3 2 1)) ;; (just 2)

(find (λ (x) (< x 0)) '(10 11 3 2 1))       ;; nothing
(find-index (λ (x) (< x 0)) '(10 11 3 2 1)) ;; nothing

【讨论】:

  • 是否应该将这些功能添加到functional-lib 某处?
  • @AlexisKing 我很高兴你这么认为。我以前从来没有为球拍包做过贡献,所以我可能不是让他们添加的最有效的人。你能想出其他方法来改进程序吗?
  • 从某种意义上说,将它们放在collections-lib 中是最有意义的,但不幸的是,该库早于functional-lib,并且它的API 中没有使用data/maybe。我想知道是否可以稍微优雅地添加一个替代 API。
  • @AlexisKing typed/racket 用户使用普通的 racket 包很常见吗?有没有提高互操作性的好方法?
  • 啊,我认为这取决于包。 require/typed 形式使得在 TR 中使用简单的无类型包变得相当容易,但 TR 无法处理 functional-libcollections-lib,因为它们使用 racket/generic,并且 TR 不(当前)支持泛型。使事情互操作良好的最简单方法是在 Typed Racket 中编写它们,因为您几乎总是可以使用来自非类型代码的 TR 代码,但反之亦然。当然,我真的很喜欢 TR 不支持的一些 Racket 特性(比如泛型),所以我的很多包都与 TR 不兼容。
【解决方案2】:

由于hdx 的头部,所以(finind x hd) 将始终为零。

尚不清楚 Pr 类型的用途,但从评论中听起来您想要一个可选对。
您可以使用累加器参数获取索引:

(: find-index : (Integer -> Boolean) (Listof Integer) -> (Option (Pair Integer Integer)))
(define (find-index pred? ls)
  (: find-help : (Listof Integer) Integer -> (Option (Pair Integer Integer)))
  (define (find-help ls i)
    (cond [(null? ls) 'None]
          [(pred? (car ls)) (Some (cons i (car ls)))]
          [else (find-help (cdr ls) (+ i 1))]))
  (find-help ls 0))

(我自己制作了Option 类型;您的可能会有所不同。)
试运行:

> (find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 9))
- : (U 'None (Some (Pairof Integer Integer)))
(Some '(2 . 9))
> (find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 49))
- : (U 'None (Some (Pairof Integer Integer)))
'None
> (find-index (lambda ([t : Integer]) (< t 10)) (list 9 41 9))
- : (U 'None (Some (Pairof Integer Integer)))
(Some '(0 . 9))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 2020-06-06
    • 2012-08-25
    • 2017-08-03
    • 1970-01-01
    • 2020-08-03
    相关资源
    最近更新 更多