【问题标题】:Scheme - Finding all indexes of occurrences of a list element方案 - 查找列表元素出现的所有索引
【发布时间】:2017-03-02 15:11:59
【问题描述】:

这里是 Stack Overflow 的新成员。我正在尝试查找 Scheme 中所有出现的元素的索引,但我不确定如何将我的代码推进到以下内容 - 打印第一次出现 - 也许有人可以帮忙:

(define positions
  (lambda (A L)
    (if (null? L)
        -1
        (if (eq? (car L) A)
            0
            (if (= (positions A (cdr L)) -1) 
                -1
                (+ 1 (positions A (cdr L))))))))

【问题讨论】:

  • 提示:尝试使用能够正确对齐表达式的编辑器。这简化了 Scheme 中的生活。以Emacs 为例。
  • 特别是emacs 和paredit。

标签: scheme


【解决方案1】:

您需要一个助手来保存额外的变量,例如您正在检查的当前索引:

(define (positions needle haystack)
  (define (helper index haystack result)
    (cond (<haystack empty> result)
          (<first element matches needle> 
           <recurse increment index, cdr haystack and cons index to result>)
          (else <recurse increment index, cdr haystack, same result>)))
  (helper 0 haystack '()))

注意(define (a args ...) body ...) 与(define a (lambda (args ...) body ...)) 相同。

【讨论】:

    【解决方案2】:

    您的代码没有使用任何类型的循环。为了获得所有事件,您必须以某种方式进行迭代。

    在Scheme 中,这通常通过named let 递归来完成。在每次迭代期间,您有一个索引变量i、结果列表r 和剩余的输入列表L,在每个迭代步骤中都会变小。

    您的示例中的if 子句可以简化。

    如果您在列表的第一个元素中找到值,则增加索引,将当前索引附加到结果列表并继续输入列表的其余部分。

    如果您没有匹配项,则增加索引,但不要将索引添加到结果列表并继续使用剩余的输入列表。

    当L 为空时,您已到达输入列表的末尾。在这种情况下,返回结果列表。您必须反转结果列表,因为cons 附加在开头。

    (define positions
      (lambda (A L)
        (let loop ((i 0)
                   (r '())
                   (L L))
          (if (null? L)
              (reverse r)
              (if (eq? (car L) A)
                  (loop (+ i 1) (cons i r) (cdr L))
                  (loop (+ i 1) r (cdr L)))))))
    

    您可以通过将 if 子句放入循环的参数中来避免输入两次循环命令。

    (define positions
      (lambda (A L)
        (let loop ((i 0)
                   (r '())
                   (L L))
          (if (null? L)
              (reverse r)
              (loop (+ i 1)
                    (if (eq? (car L) A)
                        (cons i r)
                        r)
                    (cdr L))))))
    

    顺便说一句:Scheme 不是静态类型为 C 或 Java。这意味着您不需要像在 C 中使用 -1 那样对保留变量值中的错误进行编码。在 Scheme 中,您返回 false #f 或空列表 '(),或者使用 (error "Sorry") 抛出错误。

    【讨论】:

    • 感谢您的帮助。有没有一种方法可以在您执行以下操作时做到这一点:define positions N A L 此函数的参数 N 标识应赋予列表中第一个元素的数字。
    • “给列表中的第一个元素一个数字”是什么意思?
    • @GavinColl 是的,我的回答是这样。命名为let 只是制作辅助函数的一种奇特方式。
    【解决方案3】:

    加上@ceving 的回答,cond 也可以用在循环中,可以使代码更清晰:

    (define (positions A L)
      (let loop ((i 0)
                 (r '())
                 (L L))
        (cond
          [(null? L)
           (reverse r)]
          [(eq? (car L) A)
           (loop (+ i 1) (cons i r) (cdr L))]
          [else
           (loop (+ i 1) r (cdr L))]  
          )))
    

    【讨论】:

      【解决方案4】:

      第一个观察结果是,要返回 all 解决方案,该函数应返回索引列表。如果没有找到一个元素,那么它应该返回空列表。

      第二个观察是,无论是否找到该元素,搜索都应该在列表的其余部分继续。

      第三,我们需要一个额外的参数来跟踪当前位置。

      (define positions
        (lambda (A L i)
          (if (null? L)
              '()                                       ; not found
              (if (equal? (car L) A)
                  (cons i                               ; found at index i
                        (positions A (cdr L) (+ i 1)))  ;   and continue
                  (positions A (cdr L) (+ i 1))))))     ; not found, continue
      
      > (positions 'a '(a b a c a d) 0)
      '(0 2 4)
      

      【讨论】:

        猜你喜欢
        • 2014-01-14
        • 1970-01-01
        • 1970-01-01
        • 2011-09-11
        • 2012-11-08
        • 2021-01-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多