From: Colin Bartlett Date: 2010-03-21T19:22:31+09:00 Subject: Re: Grouping elements of an array On Sun, Mar 21, 2010 at 7:58 AM, Tanaka Akira wrote: > We need two blocks. > One for slice condition and one for sliced array. > But Ruby's method call can take only one block at most. > > Enumerable#slice_before solves this problem by returning enumerator. > > enum.slice_before {|elt| condition }.each {|ary| ... } > > slice_between presented in [ruby-talk:359384] is similar. > > enum.slice_between {|elt1, elt2| condition }.each {|ary| ... } > > Another possible idea is using Proc argument. > enum.foo(lambda {|elt| condition }) {|ary| ... } > -- > Tanaka Akira I must admit that when I made my post I was having difficulty following your code for Enumerable#slice_between and the result you show for it of [["A"], ["B"], ["C", "D", "E"], ["F", "G"]] isn't (I think) what the original poster wanted. But I've just changed your condition of (t2-t1) < 30 to ! ( (t2-t1) < 30 ) and that gives the wanted result of: [["A", "B", "C"], ["D"], ["E", "F"], ["G"]] and it was that that made my realise the meaning of "slice_between". One issue here is is it going to be usually better to "group by similarity" or "slice at difference", which might affect what one calls such a method, and what condition is tested? For what I was doing it made sense to me to think in terms of grouping. As posted, Steve Wilhelm's problem was in terms of grouping, but could be thought of as slicing at "difference"? I hadn't thought of using a Proc argument for the comparison. I've just amended my Enumerable#each_group to do that, and that looks (to my tired eyes at the moment!) cleaner than what I had before. So thanks for that Proc idea. (And it runs in 1.8 as well as in 1.9, which isn't the case if you use Enumerable::Enumerator?) def group_for_sw2( arr ) lambda_compare = lambda { |aa, bb| if bb[1] - aa[1] < 30 then 0 else -1 end } arrg = [] arr.each_group( lambda_compare ) do | aa | aa.map! { |cc| cc[0] } # to preserve A, B, C objects, omit this arrg << aa end arrg end Colin Bartlett