tag:www.rhnh.net,2008:/array Array - Xavier Shay's Blog 2009-08-10T20:12:55Z Enki Xavier Shay notreal@rhnh.net tag:www.rhnh.net,2008:Post/800 2009-08-10T19:48:00Z 2009-08-10T20:12:55Z Benchmarks for creating a new array <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt>7<tt> </tt>8<tt> </tt>9<tt> </tt><strong>10</strong><tt> </tt>11<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">'</span><span class="k">benchmark</span><span class="dl">'</span></span><tt> </tt><tt> </tt>n = <span class="i">1000</span><tt> </tt>m = <span class="i">50000</span><tt> </tt>blank = [<span class="i">0</span>] * m<tt> </tt><span class="co">Benchmark</span>.bm(<span class="i">7</span>) <span class="r">do</span> |x|<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k">.new with block:</span><span class="dl">&quot;</span></span>) { (<span class="i">0</span>..n).collect { <span class="co">Array</span>.new(m) { <span class="i">0</span> } }}<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k"> .new no block:</span><span class="dl">&quot;</span></span>) { (<span class="i">0</span>..n).collect { <span class="co">Array</span>.new(m, <span class="i">0</span>) }}<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k"> [0] * x:</span><span class="dl">&quot;</span></span>) { (<span class="i">0</span>..n).collect { [<span class="i">0</span>] * m }}<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k"> #dup:</span><span class="dl">&quot;</span></span>) { (<span class="i">0</span>..n).collect { blank.dup }}<tt> </tt><span class="r">end</span><tt> </tt></pre></td> </tr></table> <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">$ ruby19 benchmark.rb <tt> </tt> user system total real<tt> </tt>.new with block: 10.180000 0.210000 10.390000 ( 10.459538)<tt> </tt> .new no block: 3.690000 0.210000 3.900000 ( 3.915348)<tt> </tt> [0] * x: 4.280000 0.210000 4.490000 ( 4.505334)<tt> </tt> #dup: 0.000000 0.000000 0.000000 ( 0.000491)<tt> </tt></pre></td> </tr></table> <p>Know your constructors! What is <code>#dup</code> doing? I think it&#8217;s cheating.</p> tag:www.rhnh.net,2008:Post/224 2007-11-13T06:10:00Z 2007-11-15T06:01:00Z Array#collapse <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt>7<tt> </tt>8<tt> </tt>9<tt> </tt><strong>10</strong><tt> </tt>11<tt> </tt>12<tt> </tt>13<tt> </tt>14<tt> </tt>15<tt> </tt>16<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">module</span> <span class="cl">CoreExtensions</span><tt> </tt> <span class="r">module</span> <span class="cl">Array</span><tt> </tt> <span class="r">def</span> <span class="fu">collapse</span><tt> </tt> <span class="pc">self</span>.inject([]) <span class="r">do</span> |a, v|<tt> </tt> <span class="r">if</span> existing = a.find {|o| o.eql?(v)}<tt> </tt> <span class="r">yield</span>(existing, v)<tt> </tt> <span class="r">else</span><tt> </tt> a &lt;&lt; v<tt> </tt> <span class="r">end</span><tt> </tt> a<tt> </tt> <span class="r">end</span><tt> </tt> <span class="r">end</span><tt> </tt> <span class="r">end</span><tt> </tt><span class="r">end</span><tt> </tt><tt> </tt><span class="co">Array</span>.send(<span class="sy">:include</span>, <span class="co">CoreExtensions</span>::<span class="co">Array</span>)<tt> </tt></pre></td> </tr></table> <p>Kind of handy for reporting, where you need to collapse line items into a summary. This example may make it clear:</p><table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt>7<tt> </tt>8<tt> </tt>9<tt> </tt><strong>10</strong><tt> </tt>11<tt> </tt>12<tt> </tt>13<tt> </tt>14<tt> </tt>15<tt> </tt>16<tt> </tt>17<tt> </tt>18<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">class</span> <span class="cl">Item</span> &lt; <span class="co">Struct</span>.new(<span class="sy">:code</span>, <span class="sy">:quantity</span>)<tt> </tt> <span class="r">def</span> <span class="fu">eql?</span>(b)<tt> </tt> code == b.code<tt> </tt> <span class="r">end</span><tt> </tt><tt> </tt> alias_method <span class="sy">:==</span>, <span class="sy">:eql?</span><tt> </tt><tt> </tt> <span class="r">def</span> <span class="fu">hash</span><tt> </tt> code.hash<tt> </tt> <span class="r">end</span><tt> </tt><tt> </tt> <span class="r">def</span> <span class="fu">to_s</span><tt> </tt> <span class="s"><span class="dl">&quot;</span><span class="il"><span class="idl">#{</span>code<span class="idl">}</span></span><span class="k"> - </span><span class="il"><span class="idl">#{</span>quantity<span class="idl">}</span></span><span class="dl">&quot;</span></span><tt> </tt> <span class="r">end</span><tt> </tt><span class="r">end</span> <tt> </tt><tt> </tt>summary = [<span class="co">Item</span>.new(<span class="s"><span class="dl">&quot;</span><span class="k">a</span><span class="dl">&quot;</span></span>, <span class="i">1</span>), <span class="co">Item</span>.new(<span class="s"><span class="dl">&quot;</span><span class="k">a</span><span class="dl">&quot;</span></span>, <span class="i">2</span>), <span class="co">Item</span>.new(<span class="s"><span class="dl">&quot;</span><span class="k">b</span><span class="dl">&quot;</span></span>, <span class="i">5</span>)].collapse {|a, b| a.quantity += b.quantity}<tt> </tt>summary.collect(&amp;<span class="sy">:to_s</span>) <span class="c"># =&gt; [&quot;a - 3&quot;, &quot;b - 5&quot;]</span><tt> </tt></pre></td> </tr></table> tag:www.rhnh.net,2008:Post/180 2007-10-23T07:46:00Z 2007-10-23T07:48:34Z Enumerable#inject is my favourite method <p><em>Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. &#8211; <a href="http://www.ruby-doc.org/core/classes/Enumerable.html#M003171">RubyDoc</a></em></p> <p>It just doesn&#8217;t sound very helpful. I must confess, it isn&#8217;t something I use everyday. But I love that when you do want to use it, it is oh so sweet. The canonical example is summing the elements in an array:</p><table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[<span class="i">1</span>,<span class="i">2</span>,<span class="i">3</span>].inject(<span class="i">0</span>) {|sum, n| sum + n} <span class="c"># =&gt; 6</span><tt> </tt></pre></td> </tr></table> <p>Probably the most used pattern is converting an array to a hash:</p><table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[<span class="i">1</span>,<span class="i">2</span>,<span class="i">3</span>].inject({}) {|a, v| a.update(v =&gt; v * <span class="i">2</span>)} <span class="c"># =&gt; {1 =&gt; 2, 2 =&gt; 4, 3 =&gt; 6}</span><tt> </tt></pre></td> </tr></table> <p>Someone in <span class="caps">IRC</span> today wanted a nested send, something like @&#8221;string&#8221;.send(&#8220;trim.downcase&#8221;)</p><table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="s"><span class="dl">&quot;</span><span class="k">trim.downcase</span><span class="dl">&quot;</span></span>.split(<span class="s"><span class="dl">'</span><span class="k">.</span><span class="dl">'</span></span>).inject(<span class="s"><span class="dl">&quot;</span><span class="k">HELLO </span><span class="dl">&quot;</span></span>) {|obj, method| obj.send(method)} <span class="c"># =&gt; &quot;hello&quot;</span><tt> </tt></pre></td> </tr></table> <p>What do you inject?</p>