Prev: openssl. question about ec
Next: [ANN] Inochi 4.0.1
From: Harry Kakueki on 28 Jul 2010 10:03 On Wed, Sep 2, 2009 at 1:41 AM, Max Williams<toastkid.williams(a)gmail.com> wrote: > > > I have a situation where i have an array of 12 items. If someone > chooses to have n of them (where n can be between 3 and 12) then i want > to always include the first and last, and then 'spread' the others out > as evenly as possible between the rest. > > So, lets say for the sake of argument that the array holds the numbers 1 > to 12. > >>> arr = (1..12).to_a > => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] > > I would get results back like this > > arr.spread(3) > => [1,6,12] (or [1,7,12], either is fine) > > arr.spread(4) > => [1, 5, 9, 12] (or [1,4,8,12] or [1, 5, 8, 12]) > >It feels like there should be a simple solution for this but i can't >think of a nice way. Anyone? > >thanks >max Thanks to a post by David Masover in a recent thread, I learned about Object#tap. He used it on a hash. I've used it here on an array. Is there any problem using Object#tap in this way? I saw some examples, but in the examples the object was not modified in the block. class Array def spread(n) dup.tap{|a| (size-n).downto(1).map{|b| size*b/(size-n+1)}.each{|c| a.delete_at(c)}} end end arr = (1..12).to_a (3..12).each{|t| p arr.spread(t)} ###Output [1, 6, 12] [1, 4, 8, 12] [1, 3, 6, 9, 12] [1, 3, 5, 8, 10, 12] [1, 2, 4, 6, 8, 10, 12] [1, 2, 4, 6, 7, 9, 11, 12] [1, 2, 3, 5, 6, 8, 9, 11, 12] [1, 2, 3, 4, 6, 7, 8, 10, 11, 12] [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] Harry
From: David Masover on 28 Jul 2010 22:40 On Wednesday, July 28, 2010 09:03:18 am Harry Kakueki wrote: > Is there any problem using Object#tap in this way? > I saw some examples, but in the examples the object was not modified > in the block. Oh, you mean modifying the array? > class Array > def spread(n) > dup.tap{|a| (size-n).downto(1).map{|b| size*b/(size-n+1)}.each{|c| > a.delete_at(c)}} > end > end Not particularly. The thing you have to be careful of is reassigning it -- for example, this wouldn't work: 1.tap {|x| x+=1} You have to actually modify the object. For example, if we're talking about arrays, instead of this: string.tap {|x| x + 'foo'} Do this: string.tap {|x| x << 'foo'} It seems like << returns self, so that's completely unnecessary, you could just do this: (string << 'foo') ...but hopefully it illustrates the point. I have a feeling I'm overcomplicating things, though. Here's one possible implementation of Object#tap: class Object def tap yield self self end end Nothing mysterious about it at all. (MRI might do it in C, I'm not sure, but the above works.)
From: Gavin Sinclair on 29 Jul 2010 00:49 On Thu, Jul 29, 2010 at 12:40 PM, David Masover <ninja(a)slaphack.com> wrote: > Do this: > > string.tap {|x| x << 'foo'} > A nice use of #tap (IMO, and these things are very much a matter of opinion): message = String.new.tap { |s| s << "..." s << "..." if some_condition? s << "..." else s << "..." end end Gavin
|
Pages: 1 Prev: openssl. question about ec Next: [ANN] Inochi 4.0.1 |