F#获取一个列表,返回元组列表

4

我做了一些研究,发现List.zip函数需要两个列表作为参数,并返回一个元组列表,但是如何将一个列表转换成元组列表呢?

let rec combinePair xs =
    match xs with
    | [] -> []
    | [x1] -> []
    | x1::x2::x3::xs -> [(x1, x2)]
    | x1::x2::xs -> [(x1, x2)] 

如果列表中存在奇数个元素,则应删除最后一个元素;如果存在偶数个元素,则应将它们返回为元组列表。例如:
combinePair [x1; x2; x3; x4] = [(x1, x2); (x3, x4)]
2个回答

5
您的代码已经接近完成了。
思路如下:
  • 当输入为空列表时,结果也是一个空列表(您已经掌握了这一点)。
  • 当输入为仅有一个元素的列表时,结果也是一个空列表(您也已经掌握了这一点)。
  • 否则,结果的第一项是由前两个元素组成的元组,剩余的结果是将同样的过程应用于输入的其余部分得到的结果。
这几乎可以完全翻译为F#:
let rec combinePair xs =
    match xs with
    | [] | [_] -> []
    | x1::x2::rest -> (x1, x2) :: (combinePair rest)

(请注意我如何将前两种情况组合在一行中,[] | [_] ->

我想我仍然不理解函数式编程的运作方式。谢谢您的帮助。 - jynx678

2

我相信有更漂亮的解决方案,但对于那些对递归过敏的人来说:

let xsOdd =  [1;2;3;4;5]

List.chunkBySize 2 xsOdd 
    |> List.filter (fun x -> x.Length = 2) 
    |> List.map (fun x -> x.[0],x.[1])
//val it : (int * int) list = [(1, 2); (3, 4)]

3
说到过敏...我对未保护的索引很过敏;-) 你可以将filtermap结合成一个,写成let combinePair2 xs = xs |> List.chunkBySize 2 |> List.choose (function | x1::x2::[] -> Some (x1, x2) | _ -> None) - Anton Schwaighofer
@AntonSchwaighofer 不错! - s952163

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接