F # Compare two lists, perform different actions

How to do this idiomatically: if a list of things is given, find if the element in it meets the criteria in another list, if it performs one action, if it does not perform another action. I saw code doing this in C #, and I was wondering how to do it in F #.

Here is the code that will be imperatively implemented in F #:

let find list1 list2 =
    for i in list1 do
        let mutable found = false
        for k in list2 do
            if i=k then    //if the criteria is equals
                found <- true
                //do task using k & i
        if found =false then   
            //do other task using i
            ()

How can this be done more functionally?

+4
source share
3 answers

The same idea as yours, only a little clearer. I turned your "criteria" into an argument function f : 'a -> 'b -> bool.

let find f xs ys = 
    xs |> List.map (fun x -> (x, List.tryFind (f x) ys))
       |> List.iter (function (x, None) -> printfn "%A" x
                            | (x, Some y) -> printfn "%A,%A" x y)

You would use it as follows:

find (=) [1;2;3;4] [1;3] (* Prints 1,1 -- 2 -- 3,3 -- 4. *)
+7
source

Short answer

let crossJoin xs ys =
    xs
    |> Seq.map (fun x -> ys |> Seq.map (fun y -> (x, y)))
    |> Seq.concat
let group f xs ys = ys |> crossJoin xs |> Seq.groupBy f

Longer answer

, , , :

let crossJoin xs ys =
    xs
    |> Seq.map (fun x -> ys |> Seq.map (fun y -> (x, y)))
    |> Seq.concat

, , :

let integers = [0 .. 10] |> List.toSeq
let strings = [0 .. 5] |> Seq.map string

:

> crossJoin integers strings |> Seq.toList;;
val it : (int * string) list =
  [(0, "0"); (0, "1"); (0, "2"); (0, "3"); (0, "4"); (0, "5"); (1, "0");
   (1, "1"); (1, "2"); (1, "3"); (1, "4"); (1, "5"); (2, "0"); (2, "1");
   (2, "2"); (2, "3"); (2, "4"); (2, "5"); (3, "0"); (3, "1"); (3, "2");
   (3, "3"); (3, "4"); (3, "5"); (4, "0"); (4, "1"); (4, "2"); (4, "3");
   (4, "4"); (4, "5"); (5, "0"); (5, "1"); (5, "2"); (5, "3"); (5, "4");
   (5, "5"); (6, "0"); (6, "1"); (6, "2"); (6, "3"); (6, "4"); (6, "5");
   (7, "0"); (7, "1"); (7, "2"); (7, "3"); (7, "4"); (7, "5"); (8, "0");
   (8, "1"); (8, "2"); (8, "3"); (8, "4"); (8, "5"); (9, "0"); (9, "1");
   (9, "2"); (9, "3"); (9, "4"); (9, "5"); (10, "0"); (10, "1"); (10, "2");
   (10, "3"); (10, "4"); (10, "5")]

crossJoin :

let group f xs ys = ys |> crossJoin xs |> Seq.groupBy f

:

> group (fun (x, y) -> x.ToString() = y) integers strings |> Seq.toList;;
val it : (bool * seq<int * string>) list =
  [(true, seq [(0, "0"); (1, "1"); (2, "2"); (3, "3"); ...]);
   (false, seq [(0, "1"); (0, "2"); (0, "3"); (0, "4"); ...])]

, true, false.

, , , :

> group (fun (x, y) -> x.ToString() = y) integers strings |> Seq.filter fst |> Seq.head |> snd |> Seq.toList;;
val it : (int * string) list =
  [(0, "0"); (1, "1"); (2, "2"); (3, "3"); (4, "4"); (5, "5")]

Seq.iter Seq.map .

, .

, , .

+4

This was the solution I came across:

let findF list1 list2 =
    list1 
    |> List.iter  (fun i ->  match (List.tryFind (fun k -> i=k) list2)  with
                         | Some(k') -> printfn "i,k=%i,%i" i k'  
                         | None     -> printfn "i=%i" i   )      

Edit: updated with comment fix.

0
source

Source: https://habr.com/ru/post/1532468/


All Articles