2017-10-08 6 views
0

Je suis très nouveau à sml/nj et je suis un peu perdu. J'ai essayé d'implémenter une fonction qui va chercher dans la liste des tuples qui ont des listes, par exemple val x = [(5,2, [9,8,7]), (3,4, [ 6,5,0]), (11, 12, [8,3,1])]. Je voudrais que ma fonction ajoute le premier élément du tuple à la nouvelle liste dès qu'il y aura une correspondance entre mon numéro cible et un nombre dans l'élément 3 du tuple. J'ai essayé plusieurs implémentations mais aucune ne fonctionne correctement jusqu'à maintenant.SML/NJ recherche dans la liste des tuples de la liste

type id = int* int* int list; 
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])] 
val number: int = 8; 
val a: int list = nil; 

fun findNum(nil) = a | findNum (x: id list) = 
    let val tem = hd(x) 
     val theList = #3tem 
     val i = #1tem 
     fun findMatch(nil) = a | findMatch(tem) = 
      if (number = hd(theList)) then i::a 
      else findMatch (tl(theList)) 
    in findNum(tl(x)) 
    end; 

findNum(b); 

Je sais que c'est mal écrit c'est pourquoi il continue de retourner la liste vide. Je me sens comme si je devais faire sinon else au lieu de let/in/end donc il va récursivement appeler le reste des tuples dans la liste. Mon problème est que je ne suis pas sûr de savoir comment le faire car si j'utilise if/else, je ne peux pas déclarer de valeur dans la fonction. J'apprécie toute suggestion ou suggestion.

Merci

+0

Pourriez-vous ajouter un exemple simple d'entrée et de sortie souhaitée, par exemple pour l'entrée '[(5,2, [9,8,7]), (3,4, [6,5,0]), (11, 12, [8,3,1])] quelle sortie attendez-vous? – coder

+0

Je m'attends à ce qu'il renvoie la liste des premiers éléments de tuples une fois que le nombre dans le troisième élément correspond. Cela devrait donc être [5, 11] dans ce cas. –

+0

Merci beaucoup. –

Répondre

1

Vous pouvez commencer par une fonction member (x, xs) qui est vrai si x est un élément dans la liste xs:

fun member (x, xs) = List.exists (fn y => x = y) xs 

Un cas de base est lorsque la liste des trois tuples est vide . Alors x ne se produit pas dans le troisième élément de l'un des trois-tuples (inexistants), et la liste des résultats est vide. Un cas récursif est obtenu par correspondance de modèle par rapport au premier élément de la liste étant un trois-tuple, (i,j,xs), et la fin de la liste, ts, et demander si x est un membre de ce troisième élément xs; si elle est, retourner la première partie du tuple, i:

fun find (x, []) = [] 
    | find (x, (i,j,xs)::ts) = 
    if member (x, xs) 
    then i :: find (x, ts) 
    else find (x, ts) 

Une version plus courte en utilisant la liste d'ordre supérieur Combinators map et filter:

fun find (x, ts) = map #1 (filter (fn (i,j,xs) => member (x, xs)) ts) 
+0

Merci beaucoup pour votre aide et votre explication. Cette implémentation est très courte et propre. –

0

Voici ma mise en œuvre avec quelques légères modifications :

type id = int* int* int list; 
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])] 
val number: int = 8; 

fun findNum [] = [] 
    | findNum (x::xs) = 
     let 
      val theList :int list = #3 (x :id) 
      val i : int = #1 x 
      fun findMatch [] = false 
      | findMatch (y::ys) = if (number = y) then true 
            else findMatch ys 
     in 
      if (findMatch theList = true) then i ::(findNum xs) 
      else (findNum xs) 
     end; 

Exemple:

- findNum b; 
val it = [5,11] : int list 
+0

C'est génial. Merci beaucoup. –

+0

Heureux d'aider !!! – coder

+1

Vos if-then-elses peuvent être raccourcis un peu. 'if (number = y) alors vrai else findMatch ys' est équivalent à' number = y orelse findMatch ys'. De même, 'if (findMatch theList = true) alors ...' peut être raccourci à 'si findMatch theList alors ...'. –