I have a NameValueCollection which I need to convert to a Map and I just can't work it out. I tried:
let headerMap (m : MailMessage) = m.Headers |> Map.map (fun k v -> v.[k])
Do I need to use Seq.map instead?
Basically the point of this is that I want to serialize the headers in a System.Net.MailMessage to JSON.
Daniel's answer will work just fine, but I thought I'd offer some additional alternatives:
Array.fold -- This should be faster than Daniel's version since it avoids the overhead of the iterators.
let mapOfNameValueCollection (collection : NameValueCollection) =
(Map.empty, collection.AllKeys)
||> Array.fold (fun map key ->
let value = collection.[key]
Map.add key value map)
Array.fold with sets of values -- Similar to the code above, but returns the value as a Set<string>
which may be useful if you want to determine if some value is in the returned set of values.
let mapOfNameValueCollection (collection : NameValueCollection) =
(Map.empty, collection.AllKeys)
||> Array.fold (fun map key ->
let valueSet =
match collection.[key] with
| null ->
Set.empty
| values ->
Set.ofArray <| values.Split [| ',' |]
Map.add key valueSet map)
Recursive loop -- Creates the map item-by-item with a recursive loop. I wouldn't use this in practice because the Array.fold
version would be easier and faster. However, this approach could be faster if the specific collection class you're using (derived from NameValueCollection
) overrides the AllKeys
property and has some weird internal behavior which takes a long time to return the property value.
let mapOfNameValueCollection (collection : NameValueCollection) =
let rec createMap map idx =
if idx < 0 then map
else
let itemName = collection.GetKey idx
let itemValue = collection.[itemName]
let map = Map.add itemName itemValue map
createMap map (idx - 1)
createMap Map.empty (collection.Count - 1)
Imperative loop -- Creates the map item-by-item with an imperative loop. As with the recursive loop, I'd prefer to use Array.fold
in practice unless there was some special reason not to.
let mapOfNameValueCollection (collection : NameValueCollection) =
let mutable map = Map.empty
let maxIndex = collection.Count - 1
for i = 0 to maxIndex do
let itemName = collection.GetKey i
let itemValue = collection.[itemName]
map <- Map.add itemName itemValue map
map