10

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

4

3 回答 3

16

奇怪的是,Racket 中没有内置过程来查找列表中元素的从 0 开始的索引(相反的过程确实存在,它被称为list-ref)。但是,高效实施并不难:

(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,它被调用了list-index,你可以通过传递正确的参数来获得想要的效果:

(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 开始,index-of现在是标准库的一部分。享受!

于 2013-04-08T04:13:26.080 回答
6

这是一个非常简单的实现:

(define (index-of l x)
  (for/or ([y l] [i (in-naturals)] #:when (equal? x y)) i))

是的,应该将这样的东西添加到标准库中,但是这样做有点棘手,所以还没有人到达那里。

但是请注意,这是一个很少有用的功能——因为列表通常被视为一个仅使用第一个/其余习语而不是直接访问元素来解构的序列。不仅如此,如果您对它有用并且您是新手,那么我的第一个猜测是您在滥用列表。鉴于此,添加这样的功能可能会通过使其更易于访问而使这些新手绊倒。(但最终仍会添加它。)

于 2013-05-29T03:33:01.647 回答
2

还可以使用内置函数 ' member',它给出一个以所需项目开头的子列表,或者#f如果列表中不存在项目。下面比较原始列表和成员返回的子列表的长度:

(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)
于 2016-12-08T04:18:21.727 回答