【问题标题】: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 为例。
  • 特别是emacsparedit

标签: 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
        相关资源
        最近更新 更多