0

I am trying to teach myself f#. For a program I am working on, I want to compare individual elements of 2 matrices, point wise. The matrices are both of size 1*N. The reason these are matrices is because they are the result of previous computations, performed using the standard F# PowerPack. I am happy to convert them to some other collection after these computations or use some other Matrix math library. What I need is a function that takes 2 matrices (which are essentially vectors) and outputs a List of index positions where the 2 vectors are not equal.

For example: Input: [[5;6;7;8;9]]; [[3;6;3;8;3]] Output: [1;3;5]

My brain still thinks very much in the imperative style and I haven't quite got my head around pattern matching yet!

Chechy Levas
  • 2,206
  • 1
  • 13
  • 28

3 Answers3

2

If you're using Powerpack you can do this:

let getDifferences x y = 
    Matrix.Generic.foldi (fun _ j s e -> if e = 0 then s else (j+1)::s) [] (x-y)
    |> List.rev // if you care about the order

By looking at your sample arrays I assume your matrices x and y are Generic matrices of type int.

If this is not the case, remove .Generic and change 0 for 0.0 but be aware that comparing floats for equality might be not a good idea, depending on your specific scenario.

Community
  • 1
  • 1
Gus
  • 25,839
  • 2
  • 51
  • 76
1

This would work for two lists:

List.zip list1 list2
|> List.mapi (fun i x -> i, x)
|> List.choose (fun (i, (a, b)) -> 
    if a = b then None else Some i)

Note, the returned indices are zero-based.

Daniel
  • 47,404
  • 11
  • 101
  • 179
0

Assuming you could extract these vectors as collections you could write (it will work without throwing exceptions if vectors have different size):

let res' = ([5;6;7;8;9], [3;6;3;8;3]) 
           ||> Seq.zip 
           |> Seq.mapi (fun i (a, b) -> if a = b then None else Some (i + 1)) 
           |> Seq.choose id

I added 1 because index in mapi function is 0-based

If you can extract vectors as lists and vectors are always of the same size you can use list functions and save one line not using List.zip:

let res'' = ([5;6;7;8;9], [3;6;3;8;3]) 
           ||> List.mapi2 (fun i a b -> if a = b then None else Some (i + 1)) 
           |> List.choose id
Petr
  • 4,280
  • 1
  • 19
  • 15