Lisp 如何在Racket中找到列表中元素的索引?
当然,这是一个微不足道的实现,但我觉得Racket中肯定有内置的东西可以做到这一点。我的直觉正确吗?如果正确,函数是什么?奇怪的是,Racket中没有一个内置的过程来查找列表中元素的基于0的索引(相反的过程确实存在,它被调用)。然而,高效实施并不难: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
(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
,会更加清晰和容易,因此这是惯用的方法