Вопрос

Постепенно осваиваясь с сопоставлением списков и хвостовой рекурсией, мне понадобилась функция, которая "сшивает" список списков вместе, оставляя промежуточные значения (легче показать, чем объяснить):

слияние [[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, потому что он обрабатывает только два уровня списка)

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

Обновить (повторный комментарий от Джульетты):Мой код создает "пути", состоящие из "сегментов", которые основаны на типе параметра:

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

Когда я создаю List.map (проект 1.) ListOfSegmentDefs, я получаю обратно список, в котором каждый сегмент начинается в той же точке, где заканчивается предыдущий сегмент.Я хочу объединить эти списки вместе, чтобы получить Путь, сохранив только "верх / хвост" каждого перекрытия - но мне не нужно делать "Набор", потому что я знаю, что у меня нет других дубликатов.

Это было полезно?

Решение

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

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 *)
    }

[Отредактируйте, чтобы добавить]:

Если вам нужна списочная версия этого кода, используйте append |> 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

Другие советы

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

или:

let merge = function
  | [] -> []
  | xs::xss -> xs @ List.collect List.tail xss
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top