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
Rob Biedenharn
2009-Aug-06 22:32 UTC
Re: split an array of hashes into an array of arrays of hashes
On Aug 6, 2009, at 3:22 PM, Nik wrote:> > 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 YouWell, 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 __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-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org
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? On Aug 6, 6:32 pm, Rob Biedenharn <R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org> wrote:> On Aug 6, 2009, at 3:22 PM, Nik wrote: > > > > > > > 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 > __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 > R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org
Rob Biedenharn
2009-Aug-07 16:14 UTC
Re: split an array of hashes into an array of arrays of hashes
On Aug 7, 2009, at 11:05 AM, Nik wrote:> 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> On Aug 6, 6:32 pm, Rob Biedenharn <R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org> wrote: >> On Aug 6, 2009, at 3:22 PM, Nik wrote: >> >>> 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 >> __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 >> >> -RobRob Biedenharn http://agileconsultingllc.com Rob-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org
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! On Aug 7, 12:14 pm, Rob Biedenharn <R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org> wrote:> On Aug 7, 2009, at 11:05 AM, Nik wrote: > > > 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 > > > > > On Aug 6, 6:32 pm, Rob Biedenharn <R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org> wrote: > >> On Aug 6, 2009, at 3:22 PM, Nik wrote: > > >>> 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 > >> __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 > R...-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org