2

我有一组数组数组的数据。举个例子

[[1,3],
 [4,3],
 [1,2],
 [7,2]]

我想将其转换为

[(3,[1,4])
 (2,[1,7])]

即:创建一个元组数组,其中第一个成员来自原始索引 1,数组是原始索引 0 的所有值,基于索引 1 分组。我可以强制解决这个问题,但我想这样做以一种更 FP 的方式

4

4 回答 4

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 ))
于 2013-03-08T11:11:40.610 回答
4

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])].

于 2013-03-10T12:04:07.013 回答
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])]
于 2013-03-08T12:43:32.450 回答
1

我的答案与上面的答案没有本质上的不同,但它使用了一些组合逻辑,所以它看起来更惯用(对我来说)。此外,它还有一些有效性检查。

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"
于 2013-03-09T14:01:57.663 回答