Collections
F#’s sequential collections all define the concat
function: Array.concat
, List.concat
, and Seq.concat
. The concat
function takes a sequence of arrays, lists, or sequences and flattens them. (In fact, some languages call this operation “flatten.”) That is, it takes the elements of the nested collections, pulls them out, and puts them all together in order in a new sequential collection, according to the type of the nested collection.
To illustrate, let’s say that the (now defunct) Java Posse podcast members and the .NET Rocks podcast members want to get together (as they did once before) to do a combined podcast—a panel, if you will, or an omni-podcast:
let javaPosse = ["Dick"; "Tor"; "Carl"; "Chet"] let dotNetRocks = ["Carl"; "Richard"] let podcasts = seq [javaPosse; dotNetRocks] // val podcasts : seq<string list> = // [ // ["Dick"; "Tor"; "Carl"; "Chet"]; // ["Carl"; "Richard"] // ]
So now you have a list of lists. To get your omni-podcast panel, you call List.concat
on podcasts
:
let panel = List.concat podcasts // val panel : string list = // ["Dick"; "Tor"; "Carl"; "Chet"; "Carl"; "Richard"]
As you can see, concat
flattens the nested lists into one long list and preserves the order of the elements as they were in the original nested lists.
Another illustration: File.ReadAllLines
reads all the lines of a file into an array. If you should need an omnibus array of all of the lines in a collection of files, you could do this:
let files = [| "file1.txt", "file2.txt" |] let allLines = files |> Array.map File.ReadAllLines // nested arrays of lines |> Array.concat // flattens nested arrays into one array // val lines : string [] = // [| // "file1 line1"; "file1 line2"; // "file2 line1"; "file2 line2"; "file2 line3"; // ... // |]
Strings
The String
module also defines a concat
function. It takes a sequence of strings and joins them all together into one string. String.concat
is a little different from the collection versions of the concat
function in that it takes two parameters: the string sequence is the second parameter, but the first is a separator or delimiter string. (Some languages call this operation “join.”)
For example, if you have a list of names that you want to concatenate together, but separate with a comma and a space, this gets you where you want to go:
let beatles = ["John"; "Paul"; "George"; "Ringo"] |> String.concat ", " // val beatles : string = "John, Paul, George, Ringo"
But if you want to make String.concat
act just like the collection versions of concat
, that is, just to jam the strings together with no delimiter, just use en empty string as your delimiter:
let atrocious = [ "super"; "cali"; "fragi"; "listic"; "expi"; "ali"; "docious" ] |> String.concat "" // val atrocious : string = // "supercalifragilisticexpialidocious"
2 replies on “F# Friday – The concat Function”
Thank you, you solved my issue! String.concat was what I was after instead of List.concat. Yay, I can move forward again. :-)
Yeah, I want that to be
String.join
so badly! Not a great name.Anyway, glad to help.