我有一组数组数组。作为一个例子
[[1,3],
[4,3],
[1,2],
[7,2]]
我想将其转换为
[(3,[1,4])
(2,[1,7])]
即:创建一个元组数组,其中第一个成员来自原始的索引1,而数组是基于索引1的原始分组的索引0的所有值。我可以强制解决这个问题,但是希望以更加FP的方式做到这一点
答案 0 :(得分:5)
将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 ))
答案 1 :(得分:4)
F#是一种静态类型的函数式编程语言,因此您要做的第一件事就是将输入转换为有类型的表示形式,例如一对int的列表:
[ 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])]
。
答案 2 :(得分:2)
与@ 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])]
答案 3 :(得分:1)
我的答案与上面的答案没有本质的不同,但它使用了一些组合逻辑,因此它看起来更像惯用语(对我来说)。此外,它还有一些有效性检查。
Apply2
基本上是S combinator。
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"