Lisp 如何在Racket中找到列表中元素的索引?

Lisp 如何在Racket中找到列表中元素的索引?,lisp,scheme,racket,Lisp,Scheme,Racket,当然,这是一个微不足道的实现,但我觉得Racket中肯定有内置的东西可以做到这一点。我的直觉正确吗?如果正确,函数是什么?奇怪的是,Racket中没有一个内置的过程来查找列表中元素的基于0的索引(相反的过程确实存在,它被调用)。然而,高效实施并不难: (define (index-of lst ele) (let loop ((lst lst) (idx 0)) (cond ((empty? lst) #f) ((equal? (firs

当然,这是一个微不足道的实现,但我觉得Racket中肯定有内置的东西可以做到这一点。我的直觉正确吗?如果正确,函数是什么?

奇怪的是,Racket中没有一个内置的过程来查找列表中元素的基于0的索引(相反的过程确实存在,它被调用)。然而,高效实施并不难:

(define (index-of lst ele)
  (let loop ((lst lst)
             (idx 0))
    (cond ((empty? lst) #f)
          ((equal? (first lst) ele) idx)
          (else (loop (rest lst) (add1 idx))))))
但是在
srfi/1
中有一个类似的过程,它被调用,您可以通过传递正确的参数来获得所需的效果:

(require srfi/1)

(list-index (curry equal? 3) '(1 2 3 4 5))
=> 2

(list-index (curry equal? 6) '(1 2 3 4 5))
=> #f
更新


从Racket 6.7开始,它现在是标准库的一部分。享受吧

下面是一个非常简单的实现:

(define (index-of l x)
  (for/or ([y l] [i (in-naturals)] #:when (equal? x y)) i))
是的,像这样的东西应该被添加到标准库中,但是这样做有点棘手,因为还没有人到达那里


但是,请注意,这是一个很少有用的特性,因为列表通常被视为一个序列,仅使用first/rest习惯用法而不是直接访问元素来解构。更重要的是,如果你是一个新手,那么我的第一个猜测是你滥用了列表。考虑到这一点,添加这样一个函数可能会让这些新手感到困惑,因为它更容易访问。(但最终仍将添加。)

还可以使用内置函数“
成员”
”,该函数提供以所需项开头的子列表,或者如果列表中不存在项,则提供以所需项开头的子列表。下面比较了原始列表和成员返回的子列表的长度:

(define (indexof n l)
  (define sl (member n l))
  (if sl 
      (- (length l)
         (length sl))
      #f))
对于许多情况,可能需要列表中所有项目的索引。可以获得所有索引的列表,如下所示:

(define (indexes_of1 x l)
  (let loop ((l l)
             (ol '())
             (idx 0))
    (cond
      [(empty? l) (reverse ol)]
      [(equal? (first l) x)
       (loop (rest l)
             (cons idx ol)
             (add1 idx))]
      [else
       (loop (rest l)
             ol
             (add1 idx))])))
For/list
也可用于:

(define (indexes_of2 x l)
  (for/list ((i l)
             (n (in-naturals))
             #:when (equal? i x))
    n))
测试:

(indexes_of1 'a '(a b c a d e a f g))
(indexes_of2 'a '(a b c a d e a f g))
输出:

'(0 3 6)
'(0 3 6)

真奇怪。racket dev邮件列表是推荐将此功能添加到语言中的合适渠道吗?我猜。。。但考虑到它的实现如此简单,这并不是什么大问题。@Maxwell我已经忘记了
列表索引
。请看我的更新答案。谢谢奥斯卡,我将使用它,你太棒了。从Racket 6.7开始,的索引现在是标准库的一部分!这可能值得编辑(尽管这个答案非常好)。请不要做
-1
的事情来表示没有索引。在这些情况下,如果您返回
#false
,会更加清晰和容易,因此这是惯用的方法