2016-11-16 2 views
0

J'ai écrit les fonctions suivantes pour find-index:Besoin d'aide pour la recherche dans une liste Racket

(: finind : (Listof Integer) Integer -> (Option Integer)) 
;; helper function for find-index 
(define (finind a b) 
    (let loop ((a a) (c 0)) 
     (cond 
     ((empty? a) 'None) 
     ((equal? (first a) b) (Some c)) 
     (else (loop (rest a) (add1 c)))))) 

(: find-index : (Integer -> Boolean) (Listof Integer) 
       -> (Option (Pr (Option Integer) Integer))) 
;; return the first item to pass the test, if there is one, 
;; along with its (0-based) index 
(define (find-index f x) 
    (match x 
     ('() 'None) 
     ((cons hd '()) 
     (if (f hd) (Some (Pr (finind x hd) hd)) 'None)) 
     ((cons hd tl) 
     (if (f hd) (Some (Pr (finind x hd) hd)) 
        (find-index f tl))))) 

Maintenant, finind fonctionne parfaitement sur lui-même, mais quand je l'utilise avec find-index, il ne retourne en arrière (Some 0). Le résultat pour (finind (list 45 41 9) 9) est (Some 2). Mais, le résultat pour (find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 9)) est (Some (Pr (Some 0) 9)), même s'il devrait être (Some (Pr (Some 2) 9)).

Donc je sais que cela peut arriver parce que j'ai (finind x hd) pour afficher mon index et parce que hd il ne change pas. Mais comment puis-je contourner cela? J'ai essayé mais en vain. Puis-je avoir une aide s'il vous plait? Je vous remercie!

+0

Dans le dernier cond cond quand le prédicat est faux, vous êtes récursif à 'find-index' et vous ne transmettez pas le décalage d'index de quelque façon que ce soit, donc il ne peut pas savoir que c'est la troisième fois que vous le faites. Peut-être envelopper avec un index et l'utiliser à la place va résoudre votre problème. – Sylwester

+0

Je ne comprends pas. Pouvez-vous donner un exemple? – testomg

+1

Vous ne passez pas ''(45 41 9)' à 'finind', vous passez la première queue dont la tête satisfait' f', qui est '' (9)'. – molbdnilo

Répondre

1

Depuis hd est la tête de x, (finind x hd) sera toujours zéro.

On ne sait pas à quoi sert le type Pr, mais à partir du commentaire, il semble que vous vouliez une paire optionnelle.
Vous pouvez obtenir l'index à l'aide d'un paramètre accumulateur:

(: find-index : (Integer -> Boolean) (Listof Integer) -> (Option (Pair Integer Integer))) 
(define (find-index pred? ls) 
    (: find-help : (Listof Integer) Integer -> (Option (Pair Integer Integer))) 
    (define (find-help ls i) 
    (cond [(null? ls) 'None] 
      [(pred? (car ls)) (Some (cons i (car ls)))] 
      [else (find-help (cdr ls) (+ i 1))])) 
    (find-help ls 0)) 

(j'ai fait mon propre type Option, la vôtre peut être différent.)
Essai de fonctionnement:

> (find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 9)) 
- : (U 'None (Some (Pairof Integer Integer))) 
(Some '(2 . 9)) 
> (find-index (lambda ([t : Integer]) (< t 10)) (list 45 41 49)) 
- : (U 'None (Some (Pairof Integer Integer))) 
'None 
> (find-index (lambda ([t : Integer]) (< t 10)) (list 9 41 9)) 
- : (U 'None (Some (Pairof Integer Integer))) 
(Some '(0 . 9)) 
1

Vous pouvez utiliser le functional-lib paquet pour rendre cela facile pour vous

(require data/maybe)  

(define (find f xs) 
    (cond ((empty? xs) nothing) 
     ((f (car xs)) (just (car xs))) 
     (else (find f (cdr xs))))) 

(define (find-index f xs (i 0)) 
    (cond ((empty? xs) nothing) 
     ((f (car xs)) (just i)) 
     (else (find-index f (cdr xs) (add1 i))))) 

(find (λ (x) (< x 10)) '(10 11 3 2 1))  ;; (just 3) 
(find-index (λ (x) (< x 10)) '(10 11 3 2 1)) ;; (just 2) 

(find (λ (x) (< x 0)) '(10 11 3 2 1))  ;; nothing 
(find-index (λ (x) (< x 0)) '(10 11 3 2 1)) ;; nothing 
+0

Ces fonctions devraient-elles être ajoutées à 'functional-lib' quelque part? –

+0

@AlexisKing Je suis flatté que vous le pensiez. Je n'ai jamais contribué à un paquet de raquette avant, donc je ne suis probablement pas la personne la plus efficace pour les ajouter. Pouvez-vous penser à d'autres moyens de rendre les procédures meilleures? – naomik

+0

Dans un certain sens, il serait plus logique pour eux d'être dans 'collections-lib', mais malheureusement cette bibliothèque est antérieure à' functional-lib', et n'utilise pas 'data/maybe' dans son API. Je me demande s'il serait possible d'ajouter une API alternative avec élégance. –