Let me take a crack at this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let combineArrays (a:string[]) (b:string[]) =
    [
        for idx in 0 .. (a.Length-1) do
        if a.[idx] <> b.[idx] then
            yield a.[idx] + "," + b.[idx]
        else
            yield a.[idx]
    ];;

(* 

> combineArrays [|"aaa";"xxx";"bbb"|] [|"aaa";"yyy";"bbb"|];;
val it : string list = ["aaa"; "xxx,yyy"; "bbb"]

*)

Of course there are other approaches which would work too and this assumes that both arrays are the same size--I leave it to you to figure out how to test that both input arrays are the same size.

By on 7/27/2010 6:05 PM ()

For same-length arrays, you can also use Zip:

1
let combine A B = Array.zip A B |> Array.map (fun (a,b) -> if a = b then a else a + "," + b)

Edit: even shorter, not constructing an immediate array, using map2:

1
let combine2 = Array.map2 (fun a b -> if a = b then a else a + "," + b)

Notice the lack of arguments to combine2, it's inferred from map2's function signature. A nice example of type inference.

By on 7/28/2010 1:29 AM ()

To generalise cfern's solution, this works on all types:

1
2
let compress a1 a2 =
    Array.map2 (fun a b -> if a = b then [|a|] else [|a; b|]) a1 a2

I'd still use lists rather than arrays but...

BTW, why does type inference fail on the following version?

1
2
3
4
let compress =
    Array.map2 (fun a b -> if a = b then [|a|] else [|a; b|])

By on 7/28/2010 3:04 AM ()

BTW, why does type inference fail on the following version?

1
2
3
4
let compress =
    Array.map2 (fun a b -> if a = b then [|a|] else [|a; b|])

It's not that inference fails - you have run into the dreaded "value restriction", which prevents you from defining a generic value (as opposed to a generic function). This is to prevent code like:

1
2
3
4
5
let test =
  let x = Array.zeroCreate 1
  fun z -> 
    printfn "%A" x.[0]
    x.[0] <- z

Here, type inference infers a type of 'a -> unit for this value; however, the array which is created on the first line is only created once, despite the fact that test true and

1
test "test"

would clearly result in storing a bool and a string into the array, respectively, which would obviously break type safety no matter how the array was initialized. To prevent these pathological definitions, F# requires generic functions to be defined using syntactic functions (i.e. they must take an explicit argument), which ensures that this kind of issue cannot arise.

By on 7/28/2010 8:08 AM ()

...

Thanks!

By on 7/28/2010 8:26 AM ()

And if you needed the orginal string/comma format, you could pipe the result to:

... |> Array.map (Array.reduce (sprintf "%s,%s"))

(With your own choice of format string.)

-Neil

By on 7/28/2010 7:54 AM ()

And if you needed the orginal string/comma format, you could pipe the result to:

1
... |> Array.map (Array.reduce (sprintf "%s,%s"))

(With your own choice of format string.)

-Neil

Or, to make it work with arbitrary types (ugh, this hurts):

1
2
3
            ...
            |> Array.map (Array.map (sprintf "%A"))
            |> Array.map (Array.reduce (sprintf "%s, %s"))
By on 7/28/2010 8:40 AM ()

And if you needed the orginal string/comma format, you could pipe the result to:

1
... |> Array.map (Array.reduce (sprintf "%s,%s"))

(With your own choice of format string.)

-Neil

Or, to make it work with arbitrary types (ugh, this hurts):

1
2
3
            ...
            |> Array.map (Array.map (sprintf "%A"))
            |> Array.map (Array.reduce (sprintf "%s, %s"))

Or, since

1
Array.map f >> Array.map g

is the same as

1
Array.map (f >> g)

(at least for pure f and g):

1
2
            ...
            |> Array.map (Array.map (sprintf "%A") >> Array.reduce (sprintf "%s, %s"))
By on 7/28/2010 8:55 AM ()

Hehehe, I was trying to figure out how to get a composition operator as the last thing before the format, and that's it, thanks!

-Neil

By on 7/28/2010 9:59 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper