2009-02-02 6 views
4

lentement obtenir le blocage de la liste correspondant et récursion de queue, je besoin d'une fonction qui « points » une liste de listes ensemble en laissant de valeurs intermédiaires (plus facile à montrer que d'expliquer):fusion/join suivants du seqs

fusion [[1; 2; 3]; [3; 4; 5]; [5; 6; 7]] // -> [1; 2; 3; 4; 5; 6; 7]

Le code pour la fonction List.merge ressemble à ceci:

///Like concat, but removes first value of each inner list except the first one 
let merge lst = 
    let rec loop acc lst = 
     match lst with 
     | [] -> acc 
     | h::t -> 
      match acc with 
      | [] -> loop (acc @ h) t 
      | _ -> loop (acc @ (List.tl h)) t //first time omit first value 
    loop [] lst 

(OK, ce n'est pas tout à fait comme concat, car il ne gère que deux niveaux de liste) 0 Question: Comment faire cela pour un Seq de Seqs (sans utiliser un drapeau mutable)?

MISE À JOUR (re commentaire de Juliette): Mon code crée composé 'chemins' des 'segments' qui sont basés sur un type d'option:

type SegmentDef = Straight of float | Curve of float * float 
let Project sampleinterval segdefs = //('clever' code here) 

Quand je fais un List.map (Projet 1.) ListOfSegmentDefs, je récupère une liste où chaque segment commence sur le même point où le segment précédent se termine. Je veux joindre ces listes ensemble pour obtenir un chemin, ne gardant que le 'sommet/queue' de chaque chevauchement - mais je n'ai pas besoin de faire un 'Set', parce que je sais que je n'ai pas d'autres doublons.

+0

Ce n'est pas très clair à quoi vous faites référence par "valeurs intermédiaires". Essayez-vous d'aplatir la liste et supprimer les doublons en même temps? Vous essayez de couper le premier élément de chaque sous-liste? – Juliet

Répondre

4

Ceci est essentiellement le même que votre première solution, mais un peu plus succincte:

let flatten l = 
    seq { 
     yield Seq.hd (Seq.hd l) (* first item of first list *) 
     for a in l do yield! (Seq.skip 1 a) (* other items *) 
    } 

[Modifier pour ajouter]:

Si vous avez besoin d'une version de la liste de ce code, l'utilisation ajouter |> Seq.to_list à la fin de votre méthode:

let flatten l = 
    seq { 
     yield Seq.hd (Seq.hd l) (* first item of first list *) 
     for a in l do yield! (Seq.skip 1 a) (* other items *) 
    } |> Seq.to_list 
+0

Nice, merci, j'ai oublié "rendement!" – Benjol

+0

En outre, si vous voulez une version de liste du code, il est plus facile d'utiliser seq {...} |> Seq.to_list plutôt que de lancer votre propre version de liste. – Juliet

+0

Mais va-t-il aussi «manger» des listes de listes? Je n'ai toujours pas grokked quand Seq, List et #Seq coopèrent ou non. – Benjol

4
let merge = function 
    | [] -> [] 
    | xs::xss -> xs @ [for _::xs in xss do yield! xs] 

ou:

let merge = function 
    | [] -> [] 
    | xs::xss -> xs @ List.collect List.tail xss 
+0

Cela ne compile pas. – Daniel

+0

@Daniel: Fixe! –

+1

Je ne peux pas croire qu'il n'y a pas de fonction de fusion fournie par le framework .NET ou les librairies F # intégrées? – knocte

Questions connexes