<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Merging arrays</title>
	<atom:link href="http://www.claudiocherubino.it/2009/06/13/merging-arrays/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=merging-arrays</link>
	<description>Life of a Googler</description>
	<lastBuildDate>Sat, 04 Sep 2010 11:07:11 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: James Moore</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20519</link>
		<dc:creator>James Moore</dc:creator>
		<pubDate>Tue, 16 Jun 2009 04:12:55 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20519</guid>
		<description>Here&#039;s my solution using LazyLists.  It has the virtue of taking anything that&#039;s a sequence (which means anything that implements IEnumerable, so arrays, lists, etc all work out of the box.

[fsharp]
type MergeWithLazyLists() =
  static member merge(f, x: LazyList, y: LazyList) =
    seq {
      match x, y with
      &#124; LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) when f xh yh -&gt;
        yield xh
        yield! MergeWithLazyLists.merge(f, xt, y)
      &#124; LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) -&gt;
        yield yh
        yield! MergeWithLazyLists.merge(f, x, yt)
      &#124; LazyList.Nil, LazyList.Cons(_, _) -&gt; yield! y
      &#124; LazyList.Cons(_, _), LazyList.Nil -&gt; yield! x
      &#124; LazyList.Nil, LazyList.Nil -&gt; ()
    }

  []
  static member merge(f, x: seq, y: seq) =
    MergeWithLazyLists.merge(f, (LazyList.of_seq x), (LazyList.of_seq y))

let result = MergeWithLazyLists.merge((fun x y -&gt; x &lt; y), (seq {2..6}), (seq {1..7..15}))

printfn &quot;%A&quot; (Seq.to_array result)
// [&#124;1; 2; 3; 4; 5; 6; 8; 15&#124;]
[/fsharp]</description>
		<content:encoded><![CDATA[<p>Here&#8217;s my solution using LazyLists.  It has the virtue of taking anything that&#8217;s a sequence (which means anything that implements IEnumerable, so arrays, lists, etc all work out of the box.</p>
<pre class="brush: fsharp;">
type MergeWithLazyLists() =
  static member merge(f, x: LazyList, y: LazyList) =
    seq {
      match x, y with
      | LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) when f xh yh -&gt;
        yield xh
        yield! MergeWithLazyLists.merge(f, xt, y)
      | LazyList.Cons(xh, xt), LazyList.Cons(yh, yt) -&gt;
        yield yh
        yield! MergeWithLazyLists.merge(f, x, yt)
      | LazyList.Nil, LazyList.Cons(_, _) -&gt; yield! y
      | LazyList.Cons(_, _), LazyList.Nil -&gt; yield! x
      | LazyList.Nil, LazyList.Nil -&gt; ()
    }

  []
  static member merge(f, x: seq, y: seq) =
    MergeWithLazyLists.merge(f, (LazyList.of_seq x), (LazyList.of_seq y))

let result = MergeWithLazyLists.merge((fun x y -&gt; x &lt; y), (seq {2..6}), (seq {1..7..15}))

printfn &quot;%A&quot; (Seq.to_array result)
// [|1; 2; 3; 4; 5; 6; 8; 15|]
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: gary ng</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20525</link>
		<dc:creator>gary ng</dc:creator>
		<pubDate>Sun, 14 Jun 2009 17:03:38 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20525</guid>
		<description>This is based on claudio&#039;s second verion but not using &#039;@&#039;. It does unfortunately create lots of intermediate garbage(characteristic of FP, the original Haskell friendly solution is very time and space efficient in Haskell because of the laziness) and cheat a bit using the List.rev rather than writing my own(which would add about 10 lines of code) and because of the use of &#039;reverse&#039;, I am not sure if it fits the O(n) requirement. The input as array IMO is an implementation detail and should not be a requirement as for imperative language, array is usually the fundamental construct whereas in things like F# or Haskell, list is.

[fsharp]
let ms (a1:&#039;a[]) (a2:&#039;a[]) =
 let rec _ms l1 l2 acc =
  match (l1,l2) with
   &#124; ([],[]) -&gt; acc
   &#124; (x::[],[]) -&gt; x::acc
   &#124; (x::xs,[]) -&gt; _ms xs [] (x::acc)
   &#124; ([],y::[]) -&gt; y::acc
   &#124; ([],y::ys) -&gt; _ms [] ys (y::acc)
   &#124; (x::xs,y::ys) -&gt;
     if x &lt; y then
      _ms xs l2 (x::acc)
     else
      _ms l1 ys (y::acc)

 List.to_array (List.rev (_ms (Array.to_list a1) (Array.to_list a2) []))
[/fsharp]</description>
		<content:encoded><![CDATA[<p>This is based on claudio&#8217;s second verion but not using &#8216;@&#8217;. It does unfortunately create lots of intermediate garbage(characteristic of FP, the original Haskell friendly solution is very time and space efficient in Haskell because of the laziness) and cheat a bit using the List.rev rather than writing my own(which would add about 10 lines of code) and because of the use of &#8216;reverse&#8217;, I am not sure if it fits the O(n) requirement. The input as array IMO is an implementation detail and should not be a requirement as for imperative language, array is usually the fundamental construct whereas in things like F# or Haskell, list is.</p>
<pre class="brush: fsharp;">
let ms (a1:'a[]) (a2:'a[]) =
 let rec _ms l1 l2 acc =
  match (l1,l2) with
   | ([],[]) -&gt; acc
   | (x::[],[]) -&gt; x::acc
   | (x::xs,[]) -&gt; _ms xs [] (x::acc)
   | ([],y::[]) -&gt; y::acc
   | ([],y::ys) -&gt; _ms [] ys (y::acc)
   | (x::xs,y::ys) -&gt;
     if x &lt; y then
      _ms xs l2 (x::acc)
     else
      _ms l1 ys (y::acc)

 List.to_array (List.rev (_ms (Array.to_list a1) (Array.to_list a2) []))
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: claudio</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20524</link>
		<dc:creator>claudio</dc:creator>
		<pubDate>Sun, 14 Jun 2009 14:36:27 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20524</guid>
		<description>To format F# code nicely you just have to wrap it between &#039;[ fsharp]&#039; and &#039;[ /fsharp]&#039; (without quotes and spaces after the opening bracket).

I added the tags in your comments for you.</description>
		<content:encoded><![CDATA[<p>To format F# code nicely you just have to wrap it between &#8216;[ fsharp]&#8216; and &#8216;[ /fsharp]&#8216; (without quotes and spaces after the opening bracket).</p>
<p>I added the tags in your comments for you.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Patrick Simpson</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20523</link>
		<dc:creator>Patrick Simpson</dc:creator>
		<pubDate>Sun, 14 Jun 2009 02:05:08 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20523</guid>
		<description>This code uses active patterns to approximate the list based implementation and is tail recursive:

[fsharp]
let merge_array (a:&#039;a array) b =
....let (&#124;Empty&#124;Head_Rest&#124;) (a:&#039;a array,ai) =
........if ai &lt;a&gt; b
........&#124; _ -&gt;
............System.Array.Copy(a,ai,b,bi,a.Length - ai)
............b
....let append a (c:&#039;a array,ci) =
........c.[ci]   copyToEnd b c
........&#124; a,Empty -&gt; copyToEnd a c
........&#124; Head_Rest(ah,ar),Head_Rest(bh,br) -&gt;
............if ah  append ah &#124;&gt; merge ar b
............else
................c &#124;&gt; append bh &#124;&gt; merge a br
....merge (a,0) (b,0) ((Array.create (a.Length+b.Length) Microsoft.FSharp.Core.Operators.Unchecked.defaultof),0)
[/fsharp]

how do you post code nicely here?</description>
		<content:encoded><![CDATA[<p>This code uses active patterns to approximate the list based implementation and is tail recursive:</p>
<pre class="brush: fsharp;">
let merge_array (a:'a array) b =
....let (|Empty|Head_Rest|) (a:'a array,ai) =
........if ai &lt;a&gt; b
........| _ -&gt;
............System.Array.Copy(a,ai,b,bi,a.Length - ai)
............b
....let append a (c:'a array,ci) =
........c.[ci]   copyToEnd b c
........| a,Empty -&gt; copyToEnd a c
........| Head_Rest(ah,ar),Head_Rest(bh,br) -&gt;
............if ah  append ah |&gt; merge ar b
............else
................c |&gt; append bh |&gt; merge a br
....merge (a,0) (b,0) ((Array.create (a.Length+b.Length) Microsoft.FSharp.Core.Operators.Unchecked.defaultof),0)
</pre>
<p>how do you post code nicely here?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tony Morris</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20522</link>
		<dc:creator>Tony Morris</dc:creator>
		<pubDate>Sun, 14 Jun 2009 01:43:34 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20522</guid>
		<description>@Gary
&quot;that is the problem of FP.&quot;

Quite the contrary. This is a problem of non-FP. Specifically, the lack of controlled side-effects introduces the need for strict evaluation, which is the problem. If F# were more functional, then the problem of evaluation could be eschewed more easily.</description>
		<content:encoded><![CDATA[<p>@Gary<br />
&#8220;that is the problem of FP.&#8221;</p>
<p>Quite the contrary. This is a problem of non-FP. Specifically, the lack of controlled side-effects introduces the need for strict evaluation, which is the problem. If F# were more functional, then the problem of evaluation could be eschewed more easily.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: James Hugard</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20515</link>
		<dc:creator>James Hugard</dc:creator>
		<pubDate>Sat, 13 Jun 2009 21:56:37 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20515</guid>
		<description>In other words, &#039;@&#039; is not O(n)... Not that we&#039;re trying to pick this apart, mind you :-) [sorry]</description>
		<content:encoded><![CDATA[<p>In other words, &#8216;@&#8217; is not O(n)&#8230; Not that we&#8217;re trying to pick this apart, mind you <img src='http://www.claudiocherubino.it/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  [sorry]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20521</link>
		<dc:creator>Brian</dc:creator>
		<pubDate>Sat, 13 Jun 2009 20:01:01 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20521</guid>
		<description>Here&#039;s an example that works on arrays, does not create a ton of garbage (space efficient), is tail-recursive, and still just 15 lines.  (Now if I can just make it appear with the proper formatting.)

[fsharp]
let MergeSortedArrays (a:array&lt;_&gt;) (b:array&lt;_&gt;) =
    let al, bl = a.Length, b.Length
    let r = Array.zeroCreate (al+bl)
    let ri = ref 0
    let inline Yield x = r.[!ri] &lt;- x; incr ri
    let rec Merge ai bi =
        if not(ai &gt;= al &amp;&amp; bi &gt;= bl) then
            if bi &gt;= bl &#124;&#124; ai &lt; al &amp;&amp; a.[ai] &lt; b.[bi] then
                Yield a.[ai]
                Merge (ai+1) bi
            else
                Yield b.[bi]
                Merge ai (bi+1)
    Merge 0 0
    r

// some tests
printfn &quot;%A&quot; ([&#124;1..6&#124;] = MergeSortedArrays [&#124;1..4&#124;] [&#124;5;6&#124;])
printfn &quot;%A&quot; ([&#124;1..6&#124;] = MergeSortedArrays [&#124;5;6&#124;] [&#124;1..4&#124;])

let N = 40000
let a1 = Array.init N (fun x -&gt; 2 * x + 1)  // 1, 3, 5, ...
let a2 = Array.init N (fun x -&gt; 2 * x)  // 0, 2, 4, ...
let r = MergeSortedArrays a1 a2
let expected = [&#124; 0..2*N-1 &#124;]
printfn &quot;%A&quot; (r = expected)
[/fsharp]</description>
		<content:encoded><![CDATA[<p>Here&#8217;s an example that works on arrays, does not create a ton of garbage (space efficient), is tail-recursive, and still just 15 lines.  (Now if I can just make it appear with the proper formatting.)</p>
<pre class="brush: fsharp;">
let MergeSortedArrays (a:array&lt;_&gt;) (b:array&lt;_&gt;) =
    let al, bl = a.Length, b.Length
    let r = Array.zeroCreate (al+bl)
    let ri = ref 0
    let inline Yield x = r.[!ri] &lt;- x; incr ri
    let rec Merge ai bi =
        if not(ai &gt;= al &amp;&amp; bi &gt;= bl) then
            if bi &gt;= bl || ai &lt; al &amp;&amp; a.[ai] &lt; b.[bi] then
                Yield a.[ai]
                Merge (ai+1) bi
            else
                Yield b.[bi]
                Merge ai (bi+1)
    Merge 0 0
    r

// some tests
printfn &quot;%A&quot; ([|1..6|] = MergeSortedArrays [|1..4|] [|5;6|])
printfn &quot;%A&quot; ([|1..6|] = MergeSortedArrays [|5;6|] [|1..4|])

let N = 40000
let a1 = Array.init N (fun x -&gt; 2 * x + 1)  // 1, 3, 5, ...
let a2 = Array.init N (fun x -&gt; 2 * x)  // 0, 2, 4, ...
let r = MergeSortedArrays a1 a2
let expected = [| 0..2*N-1 |]
printfn &quot;%A&quot; (r = expected)
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: gary ng</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20517</link>
		<dc:creator>gary ng</dc:creator>
		<pubDate>Sat, 13 Jun 2009 18:16:12 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20517</guid>
		<description>that is the problem of FP. that nice and simple to reason solution has severe real world limitation.

I would suggest do a reverse(may be double reverse) and stick to &#039;::&#039;, as &#039;@&#039; is a very expensive operation.</description>
		<content:encoded><![CDATA[<p>that is the problem of FP. that nice and simple to reason solution has severe real world limitation.</p>
<p>I would suggest do a reverse(may be double reverse) and stick to &#8216;::&#8217;, as &#8216;@&#8217; is a very expensive operation.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: claudio</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20518</link>
		<dc:creator>claudio</dc:creator>
		<pubDate>Sat, 13 Jun 2009 17:42:55 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20518</guid>
		<description>@James: arrays can be used instead of lists, only a few changes are required. Part of your code is missing, can you resend it?

@gary: a tail recursive version follows, as usual I find the original version easier to understand and therefore better suited for a didactic post.

[fsharp]
let tail_merge_arrays a b =
  let rec merge c d acc =
    match (c, d) with
    &#124; ([], []) -&gt; acc
    &#124; (c, []) -&gt; acc @ c
    &#124; ([], d) -&gt; acc @ d
    &#124; (x::xs, y::ys) -&gt;  if (x &lt; y) then
                            merge xs (y::ys) (acc @ [x])
                         else
                            merge (x::xs) ys (acc @ [y])
  merge a b []
[/fsharp]</description>
		<content:encoded><![CDATA[<p>@James: arrays can be used instead of lists, only a few changes are required. Part of your code is missing, can you resend it?</p>
<p>@gary: a tail recursive version follows, as usual I find the original version easier to understand and therefore better suited for a didactic post.</p>
<pre class="brush: fsharp;">
let tail_merge_arrays a b =
  let rec merge c d acc =
    match (c, d) with
    | ([], []) -&gt; acc
    | (c, []) -&gt; acc @ c
    | ([], d) -&gt; acc @ d
    | (x::xs, y::ys) -&gt;  if (x &lt; y) then
                            merge xs (y::ys) (acc @ [x])
                         else
                            merge (x::xs) ys (acc @ [y])
  merge a b []
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: gary ng</title>
		<link>http://www.claudiocherubino.it/2009/06/13/merging-arrays/comment-page-1/#comment-20520</link>
		<dc:creator>gary ng</dc:creator>
		<pubDate>Sat, 13 Jun 2009 17:15:40 +0000</pubDate>
		<guid isPermaLink="false">http://www.claudiocherubino.it/?p=150#comment-20520</guid>
		<description>nice solution for haskell(because of its laziness) but not so good for F# as it is not tail recursive and would have stack overflow error when the list is up to certain size.

Either it needs to be transformed to a tail call format or use the Lazy library or the &#039;yield&#039; construct.</description>
		<content:encoded><![CDATA[<p>nice solution for haskell(because of its laziness) but not so good for F# as it is not tail recursive and would have stack overflow error when the list is up to certain size.</p>
<p>Either it needs to be transformed to a tail call format or use the Lazy library or the &#8216;yield&#8217; construct.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
