4

慢慢掌握了列表匹配和尾递归的窍门,我需要一个函数将列表列表“缝合”在一起,留下中间值(显示比解释更容易):

合并 [[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 of Seqs 执行此操作(不使用可变标志)?

更新(来自朱丽叶的评论):我的代码创建了由基于选项类型的“段”组成的“路径”:

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

当我执行 List.map (Project 1.) ListOfSegmentDefs 时,我会返回一个列表,其中每个段开始于前一个段结束的同一点。我想将这些列表连接在一起以获得一个路径,只保留每个重叠的“顶部/尾部” - 但我不需要做一个“设置”,因为我知道我没有任何其他重复项。

4

2 回答 2

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

[编辑添加]:

如果您需要此代码的 List 版本,|> Seq.to_list请在方法末尾使用 append :

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
于 2009-02-03T03:34:26.090 回答
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
于 2010-07-08T23:22:01.640 回答