How can I call Enumerable.Join from F #?

I have two sequences (tuples) on which I need to make a connection:

  • Seq 1: [(City1 * Pin1), (City2 * Pin2), (City1 * Pin3), (City1 * Pin4)]
  • Seq 2: [(Pin1 * ProductA), (Pin2 * ProductB), (Pin1 * ProductC), (Pin2 * ProductA)]

in sequence (tuples):

  • [(City1 * ProductA), (City2 * ProductB), (City * ProductC), (City2 * Product A) ...]

In C #, I could do this using the Linq Join extension method, for example:

seq1.Join(seq2, t => t.Item2, t=> t.Item1,
    (t,u) => Tuple.Create(t.Item1, u.Item2))

How to do it in F #? I can not find the connection on Seq there.

+5
source share
3 answers

Edit: Actually, you can just use LINQ:

> open System.Linq;;
> let ans = seq1.Join(seq2, (fun t -> snd t), (fun t -> fst t), (fun t u -> (fst t, snd u)));;

F # native Seq? , LINQ. Seq.map2, :

> let mapped = Seq.map2 (fun a b -> (fst a, snd b)) seq1 seq2;;

val it : seq<string * string> =
  seq [("city1", "product1"); ("city2", "product2")]

, , seq1 seq2 - .

+6

F # :

> let seq1 = seq [("city1", "pin1"); ("city2", "pin2")];;

val seq1 : seq<string * string> = [("city1", "pin1"); ("city2", "pin2")]

> let seq2 = seq [("pin1", "product1"); ("pin2", "product2")];;

val seq2 : seq<string * string> = [("pin1", "product1"); ("pin2", "product2")]

> Seq.zip seq1 seq2;;
val it : seq<(string * string) * (string * string)> =
  seq
    [(("city1", "pin1"), ("pin1", "product1"));
     (("city2", "pin2"), ("pin2", "product2"))]
> Seq.zip seq1 seq2 |> Seq.map (fun (x,y) -> (fst x, snd y));;
val it : seq<string * string> =
  seq [("city1", "product1"); ("city2", "product2")]

, Linq , , System.Linq open System.Linq

UPDATE: :

open System

let seq1 = seq [("city1", "pin1"); ("city2", "pin2"); ("city1", "pin3"); ("city1", "pin4")]
let seq2 = seq [("pin1", "product1"); ("pin2", "product2"); ("pin1", "product3"); ("pin2", "product1")]

let joinSeq = seq { for x in seq1 do
                        for y in seq2 do
                            let city, pin = x
                            let pin1, product = y
                            if pin = pin1 then
                                yield(city, product) }
for(x,y)in joinSeq do
    printfn "%s: %s" x y

Console.ReadKey() |> ignore
+2

, , , . ( -, ), .

  • Zipping: , (, 1- , ..), , List.zip, List.map2.

    , , . Join #/LINQ, Zip.

  • : , , . Artem K :

    seq { for city, pin1 in seq1 do 
            for pin2, product in seq2 do 
              if pin1 = pin2 then yield city, product }
    

    , Join LINQ, seq2 seq1, O(seq1.Length * seq2.Length). , , Join . , Join, :

    open System.Linq
    module Seq = 
      let join (seq1:seq<_>) seq2 k1 k2 =
        seq1.Join(seq2, (fun t -> k1 t), (fun t -> k2 t), (fun t u -> t, u)) 
    

    - :

    (seq1, seq2) 
       ||> Seq.join snd fst 
       |> Seq.map (fun (t, u) -> fst t, snd u)
    

Finally, if you know that for each product there is exactly one unique city (sequences of the same length and pins are unique in both of them), then you can simply sort both sequences by pins, and then use it Zip- it can be more efficient than using Join(especially if you can keep the sequence sorted by some earlier operations).

+2
source

All Articles