split an array of hashes into an array of arrays of hashes

Hello, I have this big array of hashes: A =[ h0, h1, h2, ..., hn] some hi's' :cue key is true, others' is false. e.g., h1[:cue] = false h2[:cue] = false h3[:cue] = true h4[:cue] = false h5[:cue] = true ... hn[:cue] = ...

Again, these hashes are in an array, A.

Now, I'd like to group them into smaller arrays whose last item has a true cue so A' = [ [h1, h2, h3], [h4, h5], ... , [...] ]

Is there a built-in method to cook this up? If not, what combination of methods might you think would work most efficiently?

Thank You

Well, this seems to be a tasty dish. I took some liberty with your minimal spec, but you should see the first test for the usage that maps to your example.

#!/usr/bin/ruby -w class Array    def split_when      result = []      each do |element|        result[-1] << element        if block_given? ? yield(element) : element          result <<        end      end      result.pop if result.last.empty?      result    end end

if File.expand_path($0) == File.expand_path(__FILE__) require 'test/unit' class SplitWhenTest < Test::Unit::TestCase    def setup      h1 = { :cue => false }      h2 = { :cue => false }      h3 = { :cue => true }      h4 = { :cue => false }      h5 = { :cue => true }      @ary = [ h1, h2, h3, h4, h5 ]      @expected = [ [h1, h2, h3], [h4, h5] ]    end

   def test_example_from_email      assert_equal @expected, @ary.split_when {|e| e[:cue]}    end

   def test_simple      original = [ false, true, false, false, true, true, false, true, false, true, false ]      expected = [[false, true],[false, false, true],[true],[false, true],[false, true],[false]]      assert_equal expected, original.split_when, "no block"      assert_equal expected, original.split_when {|e|e}, "simple block"    end end __END__

:code/ruby $ ./array_split_when.rb Loaded suite ./array_split_when Started .. Finished in 0.000585 seconds.

2 tests, 3 assertions, 0 failures, 0 errors

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

Thanks Rob, in line 6 (where #!/usr/bin/ruby -w is line 1) where results[-1]<<element, is there a check to verify that the element's cue is true and henceforth start a new and empty array?

Thanks Rob, in line 6 (where #!/usr/bin/ruby -w is line 1) where results[-1]<<element, is there a check to verify that the element's cue is true and henceforth start a new and empty array?

No, but lines 7..9 do and line 11 discards the empty array when the last element was a cutoff (element[:cue] in this case) and was not needed to hold other elements.

-Rob

Hey Rob,

Just got a very simple version to work. Based on your code

  def self.split_when(*value)     results = []     each do |element|       results.last << element       if value.include?(element)         results <<       end     end     results   end

So, again, A = [h1, h2, h3, h4, h5, ..., hn] and some for some hi, hi[:cue] = true. I then run

A.split_when({:cue=>true})

to get

[[h1,h2,h3], [h4, h5], ... , [hj,...,hn] ]

Thanks again for the detailed code!