我有一组数组数组的数据。举个例子
[[1,3],
[4,3],
[1,2],
[7,2]]
我想将其转换为
[(3,[1,4])
(2,[1,7])]
即:创建一个元组数组,其中第一个成员来自原始索引 1,数组是原始索引 0 的所有值,基于索引 1 分组。我可以强制解决这个问题,但我想这样做以一种更 FP 的方式
我有一组数组数组的数据。举个例子
[[1,3],
[4,3],
[1,2],
[7,2]]
我想将其转换为
[(3,[1,4])
(2,[1,7])]
即:创建一个元组数组,其中第一个成员来自原始索引 1,数组是原始索引 0 的所有值,基于索引 1 分组。我可以强制解决这个问题,但我想这样做以一种更 FP 的方式
Seq.groupBy
结合几张图使用会得到想要的结果
[[1;3];
[4;3];
[1;2];
[7;2]]
|> Seq.groupBy (fun (a::b) -> b)
|> Seq.map (fun (a,b) -> a,b|> Seq.toList)
|> Seq.map (fun (a,b) -> a,b|>List.map (fun (c::d) -> c ))
F# 是一种静态类型的函数式编程语言,因此您要做的第一件事是将输入转换为类型表示,例如整数对列表:
[ 1, 3
4, 3
1, 2
7, 2 ]
然后,您可以Seq.groupBy
使用该snd
函数将其通过函数传递给每对的第二个元素:
|> Seq.groupBy snd
这给了你[3, [1, 3; 4, 3]; ...]
等等,所以你想映射到右手边,使用fst
函数提取值(即去掉键):
|> Seq.map (fun (k, kvs) -> k, Seq.map fst kvs)
这给出了您想要的答案:[(3, [1; 4]); (2, [1; 7])]
.
类似于@John 的回答,但假设内部集合是至少包含两个元素的数组:
[|[|1; 3|];
[|4; 3|];
[|1; 2|];
[|7; 2|]|]
|> Seq.map (fun arr -> arr.[0], arr.[1])
|> Seq.groupBy snd
|> Seq.map (fun (k, v) -> k, Seq.map fst v)
// val it : seq<int * seq<int>> = seq [(3, seq [1; 4]); (2, seq [1; 7])]
我的答案与上面的答案没有本质上的不同,但它使用了一些组合逻辑,所以它看起来更惯用(对我来说)。此外,它还有一些有效性检查。
Apply2
本质上是一个S 组合子。
let data =
[[1;3];
[4;3];
[1;2];
[7;2]]
// Apply2 operator applies two functions to x
// and returns both results as a tuple
let (.&.) f g x = f x, g x
// A naive validator for sequences
let assert' predicate message xs =
if not <| Seq.forall predicate xs then
failwith message
xs
let aggregate data =
data
// validate the input
|> assert' (List.length >> (=) 2) "All elements must be of length of two"
// essentially, convert a 2-element list to a tuple
|> Seq.map (List.head .&. (List.tail >> List.head))
// group over the second element of a tuple
|> Seq.groupBy snd
// we no longer need the key element in a tuple, so remove it
|> Seq.map (fst .&. (snd >> Seq.map fst))
aggregate data |> printf "%A"