Pregunta

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?

¿Fue útil?

Solución

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top