I have an array and I'd like to select only the elements between two specified values.
For example, I have an array that looks like this:
a = ["don't want", "don't want", "Start", "want", "want", "Stop", "don't want", "Start", "want", "Stop", "don't want"]
I want to call a method on the a array that captures the elements between "Start" and "Stop" (that includes the "Start" and "Stop" elements). The resulting array should look like this:
[["Start", "want", "want", "Stop"], ["Start", "want", "Stop"]]
I could not find a method like this, so I tried writing one:
class Array
def group_by_start_and_stop(start = "Start", stop = "Stop")
main_array = []
sub_array = []
group_this_element = false
each do |e|
group_this_element = true if e == start
sub_array << e if group_this_element
if group_this_element and e == stop
main_array << sub_array
sub_array = []
group_this_element = false
end
end
main_array
end
end
This works, but it seems perhaps unnecessarily verbose to me. So I have two questions: Does a similar method already exist? If not, are there ways to make my group_by_start_and_stop method better?
That's the perfect example where a flip-flop is useful!
a.select {|i| true if (i=="Start")..(i=="Stop")}.slice_before("Start").to_a
Not super known feature, but pretty cool nonetheless! Use it together with slice_before
, and you get exactly what you want!
a.each_with_index.select{|s, i| s.eql?("Start") or s.eql?("Stop")}
.map{|s, i| i}
.each_slice(2)
.map{|s, f| a[s..f]}
a.inject [] do |m, e|
if e == 'Start'
@state = true
m << []
end
m.last << e if @state
@state = false if e == 'Stop'
m
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With