简体   繁体   中英

How to build a list using a Map?

First of all, I have those types :

type position = float * float

type node = position

To build my Map I've written those modules :

module MyMap =
  struct
    type t = Graph.node
    let compare (a1,b1) (a2,b2) =
      if a1 > a2 then 1
       else if a1 < a2 then -1
       else if b1 > b2 then 1
       else if b1 < b2 then -1
       else 0
  end

module DistMap = Map.Make(MyMap)

In my case, I'll have a previousMap that has type val previousMap : (float * float) DistMap.t = <abstr> It contains nodes as key, and values. Let's say it is built like this :

DistMap.bindings prevMap;;
- : (node * (float * float)) list =
[((1., 1.), (2., 2.)); 
((2., 2.), (3., 3.)); 
((3., 3.), (4., 4.));
((4., 4.), (5., 5.))]

It means that (2.,2.) is the predecessor node of (1.,1.) in a graph.

What I am aiming for is to build the list that represent the path from a source node to a target node.

For example, if I had :

let build_path prevMap source target

The expected output using the previousMap would be a node (or float * float) list like this :

build_path previousMap (1.,1.) (5.,5.) -> [(1.,1.);(2.,2.);(3.,3.);(4.,4.);(5.,5.)]

So far my attempts consisted in trying to use the fold and iter function on the previousMap but they were inconclusive.

Update :

Here's an attempt I think could be close to what I want to achieve :

let build_list map source target =
  let rec build_aux acc map source x =
    if ((DistMap.find x map)) = source then source::acc
    else build_aux (DistMap.find x map)::acc source (DistMap.find x map)
    in build_aux [] map source target

However I get this error output :

356 |     else build_aux (DistMap.find x map)::acc source (DistMap.find x map)
                         ^^^^^^^^^^^^^^^^^^^^
Error: This expression has type 'a but an expression was expected of type
         'a list
       The type variable 'a occurs inside 'a list

Update 2 :

The issue has been solved, however the function isn't behaving as expected. Basically this is the pseudo-code I'd like to implement :

伪代码

How could I proceed to build such a list?

Thanks.

The problem with fold and iter is that they process nodes in an order that they determine themselves. In essence the order is based on the shape of the map, which is determined by the keys. You want to process the nodes of the map in an order determined by the values in the map.

I'm pretty sure the only way to proceed is to write your own special-purpose recursive function.

Update

In the latest code you have this expression:

build_aux (DistMap.find x map)::acc source (DistMap.find x map)

The operator precedence in OCaml that binds function arguments to functions is very tight, so this gets parsed like this:

(build_aux (DistMap.find x map)) :: (acc source (DistMap.find x map))

You need parentheses around this subexpression:

((DistMap.find x map)::acc)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM