Question

I have a collection of key/value pairs contained inside an F# Map

type node = {myFloat:float, data1:int; data2:int;}
type nodesCollection = {metaData:int nodes:Map<float,node>}

let results = processData (nodes:Map<float,node>)

The function processData returns a list of tuples with the following signature

val results : (node * int * int * int * int) List

I would like to:

  1. Only work with the first item of the tuple (i.e. node)
  2. Iterate through either the key/value pairs in the Map or the list of nodes
  3. Replace the node values in the Map with those if the list in the key exist in both
  4. If the key doesn't exist in the Map added the node from the list to the Map
  5. Return the updated Map

Ignoring the fact that the returned tuple needs to be parsed, I would do something like this in C# if I was using a Dictionary<float,node>

foreach newNode in nodesInList
{
  if (nodesCollection.nodes.Contains(newNode.myfloat))
     nodesCollection.nodes[newNode.myfloat] = node
  else
     nodesCollection.nodes.Add(newNode.myfloat, node); 
}

return nodesCollection.nodes

How would I approach this using a Map and functional style?

Was it helpful?

Solution

Fold is a general technique to manipulate state in an immutable iterative/recursive way. If you want to experiment with it in C# it's the Aggregate LINQ extension method.

In F# Map.add is actually add/replace, so you don't need to branch based on whether the key is contained.

type node = {myFloat:float; data1:int; data2:int;}
type nodesCollection = {metaData:int; nodes:Map<float,node>}

let nodeColl = { metaData = 5; nodes = Map.empty }
let results : (node * int * int * int * int) List = []

let nodes = List.map (fun (n, _, _, _, _) -> n) results

let res = List.fold (fun map e -> Map.add e.myFloat e map) nodeColl.nodes nodes
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top