2010-11-04 9 views
0

Je cherche à écrire une fonction récursive pour fusionner en entier listes F #fusion de deux listes en F # récursive

J'ai commencé avec cela, mais ne savez pas quoi faire.

let rec merge xs ys = 
    match xs with 
    | [] -> ys 
    | 

let li = [1;3;5;7;] 
let ll = [2;4;5;8;] 
+1

Que voulez-vous dire par "fusionner"? Essayez-vous d'alterner les éléments de chaque liste? Ou sont-ils toujours triés pour commencer, et vous voulez que la sortie soit également triée? – kvb

+0

@kvb Je voudrais que la liste de fusion soit triée. 1,2,3,4,5,5,7,8 –

+0

Et en guise d'indice, il est probablement plus facile de faire correspondre le motif sur 'xs' et' ys' simultanément (en utilisant 'match xs, ys avec ...') . – kvb

Répondre

6

Comme je l'ai dit dans mon commentaire, il est probablement plus facile si vous match de motif sur xs et ys simultanément:

let rec merge xs ys = 
    match xs,ys with 
    | [],l | l,[] -> l 
    | x::xs', y::ys' -> 
    if x < y then x :: (merge xs' ys) //' 
    else y :: (merge xs ys')   //' 
+0

Beau code. Cela suppose que l'entrée est triée pour commencer. –

+0

Cela peut être facilement transformé en queue récursive en créant une sous-fonction et en passant la nouvelle collection dans cet appel de fonction. – gradbot

+0

Essayez de l'utiliser avec par exemple [1; 9] et [2; 9] Il reviendra [1; 2; 9; 9]. Vous devriez simplement gérer cette clause avec 'else merge xs ys' et tout ira bien – eternity

1

Vous avez déjà l'un des cas de base droite: Si xs est vide, juste retour ys.

De même, si ys est vide, renvoie xs.

Pour le cas où les deux xs et ys ne sont pas vides, vous devez regarder ce xs et les premiers éléments de YS (appelons-les x et y):

Si x est inférieur à y, qu'il doit être inséré avant y dans la liste finale. Donc, vous prenez y et ajoutez au résultat de la fusion de la queue de xs avec ys (y compris y).

Sinon, vous devez passer en premier. Donc préfixez y au résultat de la fusion de xs (y compris x) avec la queue de ys.

0

Ce n'est pas récursive, mais si les entrées ne sont pas classés:

let merge xs ys = (Seq.append xs ys) |> Seq.sort |> Seq.toList 
0

Je ne pense pas que ce soit un problème de récursivité

let a = [1;3;5] 
let b = [2;4;6] 

let c = Seq.append a b |> Seq.sort 

sortie de la session fsi: c:

val it : seq<int> = seq [1; 2; 3; 4; ...] 
2

J'ai trouvé un moyen qui pourrait convenir à ce que le demandeur voulait. Pour ma part, j'ai dû résoudre ce même problème et j'ai reçu à peine une semaine de leçons sur F # afin que toute la syntaxe ne soit pas discutée en classe et quand j'ai vu la réponse au-dessus de l'utilisation de plusieurs correspondants (match lst1, list2 with ...) instantanément, mais le professeur ne permettait pas son utilisation, donc j'ai dû trouver cette autre alternative. Même pensé que c'est fondamentalement le même algorithme, il utilise plus de code de base. Juste pensé que je devrais poster =)

let rec merge2 list1 list2 = 
    let head list = match list with | [] -> 0 | h::t -> h 
    let tail list = match list with | [] -> [] | h::t -> t 
    match list1 with 
    | [] -> [] 
    | h::t -> 
     //list2's head is 0 then list is empty then return whats in the first list 
     //(i.e no more values of second list to compare) 
     if head list2 = 0 then list1 
     elif h < head list2 then h :: merge2 t list2 
     else head list2 :: merge2 list1 (tail list2) 
0

J'utiliseraient List.fold pour ce faire:

let merge a b = 
    List.fold (fun acc x -> 
     if List.exists ((=)x) acc = false then 
      elem :: acc 
     else 
      acc 
    ) (List.sort a) b 

Cela peut ne pas être le meilleur moyen de le faire, cependant.