nadamgm
nadamgm

Reputation: 43

How to combine two differently typed sequences into tuples in f#?

I'm a bit new to F#, I have mostly c# background. I'm working with two lists/sequences that represent the same thing, but from different datasources (one is a local file, the other is a group of items in an online system.

I need to report the mismatches between the two datasets.

So far I have filtered down the two lists to contain only items that aren't have mismatches in the other dataset.

Now I want to pair them up into tuples (or anything else really) based on one of the properties so I can log the differences.

So far what I've tried is this:

 let printDiff (offlinePackages: oP seq) (onLinePackages: onP seq) =
                                                                    Seq.map2(fun x y -> (x, y)) offlinePackages onLinePackages

This does pair up my data, however I'd still need some logic to do the pairup based on their matching property value. I'm looking for something like:

if offLinePackage.Label = OnlinePackage.Label then /do the matchup/
else /don't do anything/

I know I'm still stuck in my object oriented thinking, that's also why I'm asking.

Thanks in advance!

Upvotes: 2

Views: 120

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80744

Matching sequence elements based on some equivalency function - that's called "join".

The most "straightforward" way to do a join is to get a Cartesian product and filter it down, like this:

let matchup seq1 seq2 = 
    Seq.allPairs seq1 seq2
    |> Seq.filter (fun (x, y) -> x.someProp = y.someProp)

Or in a computation expression form:

let matchup seq1 seq2
    seq {
      for x in seq1 do
      for y in seq2 do
      if x.someProp = y.someProp then yield (x,y)
    }

But this is a bit inefficient. The complexity would be O(n*m), because it iterates over all possible pairs. Fine if the lists are short, but will bite you the more you scale.

To do this more efficiently, you can use the query computation builder and its operation join, which does a hash-join (i.e. it builds a hashtable first and then matches the elements based on that):

let matchup seq1 seq2 =
  query {
    for x in seq1 do
    join y in seq2 on (x.someProp = y.someProp)
    select (x,y)
  }

Upvotes: 4

Related Questions