Grayden Hormes
Grayden Hormes

Reputation: 875

F# find all elements present in another array

this solution

d1 |> Array.filter (fun t -> d2 |> Array.exists (fun t2 -> t=t2))

from this so answer

Finding the difference between two arrays in FSharp

gives this error

Severity    Code    Description Project File    Line    Suppression State
Error       Type mismatch. Expecting a
    unit -> bool    
but given a
    'a [] -> bool    
The type 'unit' does not match the type ''a []' ParseLibs   
Program.fs  25  

Full code:

// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.

open System
open System.IO

open FSharp.Collections

[<EntryPoint>]
let main argv = 
    let path = "data1.txt"
    let lines = use reader = new StreamReader(path) in reader.ReadToEnd().Split('\n')
    let n = 5

    let d1 = lines 
            |> Array.takeWhile (fun e -> not (e.Equals "\r")) 

    let d2 = lines 
            |> Array.skipWhile (fun e -> not (e.Equals "\r")) 
            |> Array.skip 1
            |> Array.mapi (fun i e -> e, i)
            |> Array.filter (fun (e, i) -> i % n = 0)
            |> Array.iter (fun (e, i) -> printfn "%s" e)

    d1 |> Array.filter (fun t -> d2 |> Array.exists (fun t2 -> t=t2))

    //let writer = new StreamWriter(path)

    ignore (Console.ReadKey())
    0 // return an integer exit code

Is the answer there wrong? What is the real answer? I am simply trying to filter all the elements that are in both arrays. In most functional languages this is as trivial as they come.

d1 |> Array.filter (fun t -> d2.contains(t))

Upvotes: 1

Views: 884

Answers (2)

Helge Rene Urholm
Helge Rene Urholm

Reputation: 1188

Using the actual answer from the above link: https://stackoverflow.com/a/28682277/5514938 and adding the information at https://en.wikipedia.org/wiki/Set_theory#Basic_concepts_and_notation the following code is an example of the three first concepts with same sets/values as in wiki article.

let d1= [|"1";"2";"3";|] //pretend this to be the filtered/skipped/mapped
                         //whatever but otherwise "clean" structure/datatypes
let d2 = [|"2";"3";"4";|] //pretend this to be the filtered/skipped/mapped
                          //whatever  but otherwise "clean" structure/datatypes 
                          //equal to d1


let s1 = d1 
        |> Set.ofArray

let s2 = d2 
        |> Set.ofArray


let all = s1 + s2 //Union
let inBoth = Set.intersect s1 s2 //Intersection

let onlyIn_d1 = s1 - s2 //Set difference
let onlyIn_d2 = s2 - s1 //Set difference the other way ;-)

I have removed your other code to simplify the concepts, so the initial filter, skippings and mappings you are doing must of course be done ahead of the above code. And you must also "realign" the types to be equal again:

|> Array.mapi (fun i e -> e, i)
|> Array.filter (fun (e, i) -> i % n = 0)
|> Array.map (fun (e,i) -> e)
|> Set.ofArray

Upvotes: 0

John Palmer
John Palmer

Reputation: 25516

The problem is that d2 has type unit.

As array.iter returns ()

I would change to

let d2 = lines 
        |> Array.skipWhile (fun e -> not (e.Equals "\r")) 
        |> Array.skip 1
        |> Array.mapi (fun i e -> e, i)
        |> Array.filter (fun (e, i) -> i % n = 0)

d1 
|> Array.filter (fun t -> d2 |> Array.exists (fun t2 -> t=t2)) 
|> Array.iter (fun (e, i) -> printfn "%s" e)

Upvotes: 4

Related Questions