F#将数组转换为元组数组

3

假设我有一个数组

let arr = [|1;2;3;4;5;6|]

我希望将其转换为类似以下的形式:
[|(1,2);(3,4);(5,6)|]

我看到过Seq.window,但这个会生成类似于:
[|(1,2);(2,3);(3,4);(4,5);(5,6)|]

这不是我想要的

4个回答

4
你可以使用Array.chunkBySize将数组分块,然后将每个子数组映射成元组:
let input = [|1..10|]
Array.chunkBySize 2 list |> Array.map (fun xs -> (xs.[0], xs.[1]))

3
请注意,如果数组中的项数为奇数,此解决方案会抛出 System.IndexOutOfRangeException 异常。 - hvester
我正在检查长度是否为偶数,所以这不会成为问题,但如果有人没有进行检查,这将是答案的一个很好的补充。 - AlexanderM
@hvester同意map lambda可以扩展为创建一个带有可选第二元素或其他所需行为的元组。 - Slugart

2
@Slugart的回答是最佳方法(在我看来),假设你知道数组有偶数个元素,但这里还有另一种方法,如果恰好有奇数个元素,它不会抛出异常(只是省略了最后一个尾随元素):
let arr = [|1;2;3;4;5|]
seq { for i in 0 .. 2 .. arr.Length - 2 -> (arr.[i], arr.[i+1]) } |> Seq.toArray

0

你可以使用Seq.pairwise,只要过滤掉每个元组中的另一个。过滤需要通过迭代传递状态,通常是通过scan函数实现的。

[|1..10|]
|> Seq.pairwise
|> Seq.scan (fun s t ->
    match s with None -> Some t | _ -> None )
    None
|> Seq.choose id
|> Seq.toArray
// val it : (int * int) [] = [|(1, 2); (3, 4); (5, 6); (7, 8); (9, 10)|]

但是,也有可能让scan直接生成元组,虽然会带来中间数组的惩罚。

[|1..10|]
|> Array.scan (function
| Some x, _ -> fun y -> None, Some(x, y)
| _  -> fun x -> Some x, None )
    (None, None)
|> Array.choose snd

-1
使用 Seq.pairwise 将序列转换为元组。
[|1;2;3;4;5;6|]
    |> Seq.pairwise
    |> Seq.toArray

val it : (int * int) [] = [|(1, 2); (2, 3); (3, 4); (4, 5); (5, 6)|]

应该是:

let rec slice =
    function
    | [] -> []
    | a::b::rest -> (a,b) :: slice (rest)
    | _::[] -> failwith "cannot slice uneven list"

这会生成额外的对(2,3)和(4,5),这是不希望的。 - Joh

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