TierTwo
TierTwo

Reputation: 133

How to create a list of object by using some sort of filter with a predicate

I'm iterating through a list of nodes in order to create edges between them, however I want to check if the edge between two nodes are not crossing a 'dangerous' place, so I created a function that will work as a predicate to insure I do not create a such an edge. However I don't see how I would be able to properly build my list of edges.

The types manipulated are :

type position = float * float
type node = position
type edge = position * position * float

I have written this, it doesn't work, but this is what I had in mind, I don't know what I could use in OCaml to make it work

let create_edges nodes_list =
  let rec create_edges_aux nodes =
    match nodes with
      | [] -> []
      | x::[] -> (x,x,0.) :: []
      | x::tl -> List.map (fun x2 -> if (is_safe_edge x x2) then (x,x2,extract_float(dist2 x x2))) tl @ create_edges_aux tl
    in create_edges_aux nodes_list

The problem is here obviously List.map (fun x2 -> if (is_safe_edge x x2) then (x,x2,extract_float(dist2 x x2))) tl @ create_edges_aux tl

The function works perfectly if I do this : List.map (fun x2 -> (x, x2, (extract_float (dist2 x x2)))) tl @ create_edges_aux tl but the unsafe edges aren't filtered ...

In the end my problem is that I'm not able to create a list of edges that satisfy the predicate function I coded and the goal is to be able to make that list.

If you have any ideas or solution, thanks.

Upvotes: 0

Views: 392

Answers (2)

Christophe Riolo
Christophe Riolo

Reputation: 96

What you want to do is filtering of the values, which cannot be done with List.map as it always take all the values. One first option is to first filter the edges with List.filter then map. If you use OCaml 4.08 or later you can use the dedicated List.filter_map function. If you are using an older version of OCaml you can also use List.fold_left function to do the mapping and filtering.

In short, List.map can only modify all the values, if you need to filter out some values, it's not the function you need.

Upvotes: 1

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66823

It looks to me like you just need an else part in your if.

A code pattern that you see a lot in OCaml is something like this:

let f x =
    let x' = if x > 100 then 100 else x in
    g x'

When using an if in a functional context, the if always needs an else, because the expression must have a value in both cases. Quite often the else value is the original (unmodified) input value.

Upvotes: 1

Related Questions