これはもちろん些細な実装ですが、Racket には確かにこれを行う何かが組み込まれていると思います。私はその直感で正しいですか? もしそうなら、機能は何ですか?
3 に答える
奇妙なことに、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
、標準ライブラリの一部になりました。楽しみ!
非常に単純な実装を次に示します。
(define (index-of l x)
(for/or ([y l] [i (in-naturals)] #:when (equal? x y)) i))
そして、はい、このようなものを標準ライブラリに追加する必要がありますが、それを行うのは少し難しいので、まだ誰もそこに到達していません.
ただし、これはほとんど役に立たない機能であることに注意してください。リストは通常、要素に直接アクセスするのではなく、first/rest イディオムのみを使用して分解されるシーケンスと見なされるためです。それ以上に、あなたがそれを使用していて、あなたが初心者である場合、私の最初の推測は、あなたがリストを誤用しているということです. それを考えると、そのような機能の追加は、よりアクセスしやすくすることで、そのような初心者をつまずかせる可能性があります. (ただし、最終的にはまだ追加されます。)
組み込み関数 ' member
' を使用することもできます。これは、必要なアイテムで始まるサブリストを提供するか#f
、アイテムがリストに存在しない場合に使用できます。以下は、元のリストと member によって返されたサブリストの長さを比較します。
(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)