F#: Expand a list of tuples of form (string*string list) list using a key

独自空忆成欢 提交于 2019-12-11 18:14:11

问题


The other day I asked how could reduce a list of tuples by grouping one of the elements into arrays (F#: Reduce a list of tuples by grouping one of the elements into arrays). I wish now to learn how to do the opposite of this. Lets say I have this:

("A", ["B"; "C"; "D"; "E"])

and I want to get this:

[("A", "B") ; ("A", "C") ; ("A" , "D") ; ("A" , "E")]

What is the functional way to do this? How could I do it with a list of elements of this type to be appended? I have tried:

let prb = ("A", ["B"; "C"; "D"; "E"]) |> [for i in snd -> (fst, i)]

But hasn't worked.

Thanks a lot for your answers! I am new to F# and I am sorry if this is really basic


回答1:


You can use List.map on snd source:

let source = ("A", ["B"; "C"; "D"; "E"]);;

// val source : string * string list = ("A", ["B"; "C"; "D"; "E"])

let result = snd source |> List.map (fun x -> fst source, x);;

// val result : (string * string) list =
//    [("A", "B"); ("A", "C"); ("A", "D"); ("A", "E")]

Update

For list of these elements

let source = [("A", ["B"; "C"; "D"; "E"]);("A", ["B"; "C"; "D"; "E"]);("A", ["B"; "C"; "D"; "E"])];;

// val source : (string * string list) list =
//   [("A", ["B"; "C"; "D"; "E"]); ("A", ["B"; "C"; "D"; "E"]);
//    ("A", ["B"; "C"; "D"; "E"])]

you can declare a function with code from above

let collectTuple (x, items) = items |> List.map (fun y -> x, y);;

// val collectTuple : x:'a * items:'b list -> ('a * 'b) list

and use it to call List.map:

let result = source |> List.map collectTuple;;

// val result : (string * string) list list =
//   [[("A", "B"); ("A", "C"); ("A", "D"); ("A", "E")];
//    [("A", "B"); ("A", "C"); ("A", "D"); ("A", "E")];
//    [("A", "B"); ("A", "C"); ("A", "D"); ("A", "E")]]

or List.collect if you want just one list of tuples instead:

let result = source |> List.collect collectTuple;;

// val result : (string * string) list =
//   [("A", "B"); ("A", "C"); ("A", "D"); ("A", "E"); ("A", "B"); ("A", "C");
//    ("A", "D"); ("A", "E"); ("A", "B"); ("A", "C"); ("A", "D"); ("A", "E")]



回答2:


As an alternative to using List.map, you can also use list comprehensions. For simple transformations, this is usually my preferred option, but this is really just a matter of style, so Marcin's answer is perfectly fine.

The finished version looks like this:

let collectTuple (key, values) = 
  [ for v in values -> key, v ]

In your attempted solution, you tried to use fst and snd to access the elements of the tuple, which works too:

let collectTuple input = 
  [ for v in snd input -> fst input, v ]


来源:https://stackoverflow.com/questions/25465121/f-expand-a-list-of-tuples-of-form-stringstring-list-list-using-a-key

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!