2009-02-02 7 views
4

Медленно получать навык согласования списка и хвостовую рекурсию, мне нужна функция, которая «стежки» список списков вместе оставляя от промежуточных значений (проще показать, чем объяснить):Merge/нарисуйте последующие статьи seqs

слияния [[1; 2; 3]; [3; 4; 5]; [5; 6; 7]] // -> [1; 2; 3; 4; 5; 6; 7]

Код для функции List.merge выглядит следующим образом:

///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 

(ОК, это не совсем так CONCAT, потому что он обрабатывает только два уровня списка)

Вопрос: Как это сделать для Seq Seqs (без использования изменяемого флага)?

UPDATE (вос комментарий от Juliet): Мой код создает «пути» состоит из «сегментов», которые основаны на типа опции:

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

Когда я делаю List.map (проект 1.) ListOfSegmentDefs, я возвращаю список, где каждый сегмент начинается в той же точке, где заканчивается предыдущий сегмент. Я хочу присоединиться к этим спискам вместе, чтобы получить Path, сохраняя только «верх/конец» каждого перекрытия, но мне не нужно делать «Set», потому что я знаю, что у меня нет других дубликатов.

+0

Не совсем понятно, на что вы ссылаетесь на «промежуточные значения». Вы пытаетесь сгладить список и удалить дубликаты одновременно? Пытаетесь отрубить первый элемент каждого подписок? – Juliet

ответ

4

Это, по существу, такой же, как ваш первый решение, но чуть более лаконичным:

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 в конце вашего метода:

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

Ницца, спасибо, я забыл про «урожай!» – Benjol

+0

Кроме того, если вы хотите получить версию списка кода, проще всего использовать seq {...} |> Seq.to_list, а не сворачивать собственную версию списка. – Juliet

+0

Но будет ли он «съедать» списки списков? Я все еще не grokked, когда Seq, List и #Seq сотрудничают или нет. – Benjol

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

или:

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

Это не компилируется. – Daniel

+0

@ Даниэль: Исправлено! –

+1

Не могу поверить, что нет никакой функции слияния, предоставляемой платформой .NET или встроенными F # libs? – knocte

 Смежные вопросы

  • Нет связанных вопросов^_^