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