From 62170e62188b8b2afb342bbea36b02c4946ac9df Mon Sep 17 00:00:00 2001 From: Alexis King Date: Wed, 7 Dec 2016 01:52:25 -0800 Subject: [PATCH] Add index(es)-of and index(es)-where to racket/list --- .../scribblings/reference/pairs.scrbl | 42 +++++++++++++++ pkgs/racket-test-core/tests/racket/list.rktl | 29 ++++++++++ racket/collects/racket/list.rkt | 53 +++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/pkgs/racket-doc/scribblings/reference/pairs.scrbl b/pkgs/racket-doc/scribblings/reference/pairs.scrbl index c2e579b59c..c3a46df4ba 100644 --- a/pkgs/racket-doc/scribblings/reference/pairs.scrbl +++ b/pkgs/racket-doc/scribblings/reference/pairs.scrbl @@ -898,6 +898,48 @@ The element at the specified index is @racket[value]. @history[#:added "6.3"]{} } +@defproc[(index-of [lst list?] [v any/c] + [is-equal? (any/c any/c . -> . any/c) equal?]) + (or/c exact-nonnegative-integer? #f)]{ +Like @racket[member], but returns the index of the first element found +instead of the tail of the list. + +@mz-examples[#:eval list-eval + (index-of '(1 2 3 4) 3)] + +@history[#:added "6.7.0.3"]} + +@defproc[(index-where [lst list?] [proc (any/c . -> . any/c)]) + (or/c exact-nonnegative-integer? #f)]{ +Like @racket[index-of] but with the predicate-searching behavior of +@racket[memf]. + +@mz-examples[#:eval list-eval + (index-where '(1 2 3 4) even?)] + +@history[#:added "6.7.0.3"]} + +@defproc[(indexes-of [lst list?] [v any/c] + [is-equal? (any/c any/c . -> . any/c) equal?]) + (listof exact-nonnegative-integer?)]{ +Like @racket[index-of], but returns the a list of all the indexes +where the element occurs in the list instead of just the first one. + +@mz-examples[#:eval list-eval + (indexes-of '(1 2 1 2 1) 2)] + +@history[#:added "6.7.0.3"]} + +@defproc[(indexes-where [lst list?] [proc (any/c . -> . any/c)]) + (listof exact-nonnegative-integer?)]{ +Like @racket[indexes-of] but with the predicate-searching behavior of +@racket[index-where]. + +@mz-examples[#:eval list-eval + (indexes-where '(1 2 3 4) even?)] + +@history[#:added "6.7.0.3"]} + @defproc[(take [lst any/c] [pos exact-nonnegative-integer?]) list?]{ diff --git a/pkgs/racket-test-core/tests/racket/list.rktl b/pkgs/racket-test-core/tests/racket/list.rktl index 369201a8ce..ed1a67da9e 100644 --- a/pkgs/racket-test-core/tests/racket/list.rktl +++ b/pkgs/racket-test-core/tests/racket/list.rktl @@ -673,4 +673,33 @@ (test '(1 3 -5) remf* even? '(1 -2 3 4 -5)) (test '(1 -2 3 4 -5) remf* (λ (x) #f) '(1 -2 3 4 -5)) +;; ---------- index(es)-of / index(es)-where ---------- + +(test #f index-of '() 'a) +(test #f index-of '(a b) 'c) +(test 0 index-of '(a b c) 'a) +(test 1 index-of '(a b c) 'b) +(test 0 index-of (list #'a #'b #'c) #'a free-identifier=?) +(test 1 index-of (list #'a #'b #'c) #'b free-identifier=?) + +(test #f index-where '() even?) +(test #f index-where '(1 3 5) even?) +(test 0 index-where '(1 2 3 4 5) odd?) +(test 1 index-where '(1 2 3 4 5) even?) + +(test '() indexes-of '() 'a) +(test '() indexes-of '(a b) 'c) +(test '(0) indexes-of '(a b c) 'a) +(test '(1) indexes-of '(a b c) 'b) +(test '(0 1) indexes-of '(a a b) 'a) +(test '(1 2) indexes-of '(a b b) 'b) +(test '(0 1 2) indexes-of '(a a a) 'a) +(test '(0 1) indexes-of (list #'a #'a #'b) #'a free-identifier=?) +(test '(1 2) indexes-of (list #'a #'b #'b) #'b free-identifier=?) + +(test '() indexes-where '() even?) +(test '() indexes-where '(1 3 5) even?) +(test '(1 3) indexes-where '(1 2 3 4 5) even?) +(test '(0 2 4) indexes-where '(1 2 3 4 5) odd?) + (report-errs) diff --git a/racket/collects/racket/list.rkt b/racket/collects/racket/list.rkt index f86108333f..e0f1979aac 100644 --- a/racket/collects/racket/list.rkt +++ b/racket/collects/racket/list.rkt @@ -13,6 +13,11 @@ list-update list-set + index-of + index-where + indexes-of + indexes-where + drop take split-at @@ -828,3 +833,51 @@ [else (cons (car ls) (remf* f (cdr ls)))])) + +(define (index-of ls v [=? equal?]) + (unless (list? ls) + (raise-argument-error 'index-of "list?" ls)) + (unless (and (procedure? =?) + (procedure-arity-includes? =? 2)) + (raise-argument-error 'index-of "(-> any/c any/c any/c)" =?)) + (let loop ([ls ls] + [i 0]) + (cond [(null? ls) #f] + [(=? (car ls) v) i] + [else (loop (cdr ls) (add1 i))]))) + +(define (index-where ls f) + (unless (list? ls) + (raise-argument-error 'index-where "list?" ls)) + (unless (and (procedure? f) + (procedure-arity-includes? f 1)) + (raise-argument-error 'index-where "(-> any/c any/c)" f)) + (let loop ([ls ls] + [i 0]) + (cond [(null? ls) #f] + [(f (car ls)) i] + [else (loop (cdr ls) (add1 i))]))) + +(define (indexes-of ls v [=? equal?]) + (unless (list? ls) + (raise-argument-error 'indexes-of "list?" ls)) + (unless (and (procedure? =?) + (procedure-arity-includes? =? 2)) + (raise-argument-error 'indexes-of "(-> any/c any/c any/c)" =?)) + (let loop ([ls ls] + [i 0]) + (cond [(null? ls) '()] + [(=? (car ls) v) (cons i (loop (cdr ls) (add1 i)))] + [else (loop (cdr ls) (add1 i))]))) + +(define (indexes-where ls f) + (unless (list? ls) + (raise-argument-error 'indexes-where "list?" ls)) + (unless (and (procedure? f) + (procedure-arity-includes? f 1)) + (raise-argument-error 'indexes-where "(-> any/c any/c)" f)) + (let loop ([ls ls] + [i 0]) + (cond [(null? ls) '()] + [(f (car ls)) (cons i (loop (cdr ls) (add1 i)))] + [else (loop (cdr ls) (add1 i))])))