Reputation: 1535
Consider I have an array of integer elements. In which I am trying to find the index where a long sequence of repetitive numbers begins.
my_array = [100, 101, 100, 102, 100, 100, 101, 100, 250, 251, 253, 260, 250, 200, 100, 100, 100, 100, 100, 100, 100, 100, 100, 120]
Bellow is the way I am trying to find the index. Can anyone suggest me more optimised and correct way of doing it?
my_array.each with_index do |e, x|
match = e.to_s * 5
next_10 = my_array[x + 1, 5].join()
if match == next_10
puts "index #{x}"
break
end
end
#index 14
Upvotes: 3
Views: 1129
Reputation: 1958
my_array = [100, 101, 100, 102, 100, 100, 101, 100, 250, 251, 253, 260, 250, 200, 100, 100, 100, 100, 100, 100, 100, 100, 100, 120]
index_and_repetitions = lambda { |my_array|
stk = {}
previous = my_array[0]
last_index = 0
stk[last_index] = 1
my_array.drop(0).each_with_index{|item, index|
if item == previous
stk[last_index] += 1
else
last_index = index
stk[last_index] = 1
previous = item
end
}
stk
}
stk = index_and_repetitions.call(my_array)
puts stk.key(stk.values.max)
you can find benchmark results(compared to others answers) from here.
Upvotes: 1
Reputation: 110755
I assume the objective is to find the index of the first element of the longest sequence of equal elements in the given array.
my_array = [100, 101, 100, 102, 100, 100, 101, 100, 250, 251, 253, 260, 250, 200,
100, 100, 100, 100, 100, 100, 100, 100, 100,
120]
Here that would be 14
, the index of 100
that is followed by 8 more 100
's.
We can do that as follows.
my_array.each_index.chunk { |i| my_array[i] }.
max_by { |_,a| a.size }.
last.
first
#=> 14
The steps are as follows.
enum0 = my_array.each_index
#=> #<Enumerator: [100, 101, 100,..., 100, 120]:each_index>
We can see the elements that will be generated by this enumerator by converting it to an array.
enum0.to_a
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
# 17, 18, 19, 20, 21, 22, 23]
Continuing,
enum1 = enum0.chunk { |i| my_array[i] }
#=> #<Enumerator: #<Enumerator::Generator:0x000058d8d09ec8a0>:each>
In view of the above expression's return value, enum1
could be thought of as a compound enumerator, though Ruby has no such concept. Let's see the values enum1
will generate.
enum1.to_a
#=> [[100, [0]], [101, [1]], [100, [2]], [102, [3]], [100, [4, 5]],
# [101, [6]], [100, [7]], [250, [8]], [251, [9]], [253, [10]],
# [260, [11]], [250, [12]], [200, [13]],
# [100, [14, 15, 16, 17, 18, 19, 20, 21, 22]],
# [120, [23]]]
Continuing,
a = enum1.max_by { |v,a| a.size }
#=> [100, [14, 15, 16, 17, 18, 19, 20, 21, 22]]
As v
is not used in the block, this expression would customarily be written:
a = enum1.max_by { |_,a| a.size }
The presence of the underscore (a valid local variable) signals to the reader that that block variable is not used in the block calculation. The last two steps are as follows.
b = a.last
#=> [14, 15, 16, 17, 18, 19, 20, 21, 22]
b.first
#=> 14
See Enumerable#chunk and Enumerable#max_by.
Upvotes: 1
Reputation: 5552
In first iteration, I am getting array of repeating elements sequence and then I proceed further with logic,
groups = my_array[1..-1].inject([[my_array[0]]]) { |m, n| m.last[0] == n ? m.last << n : m << [n]; m }
# => [[100], [101], [100], [102], [100, 100], [101], [100], [250], [251], [253], [260], [250], [200], [100, 100, 100, 100, 100, 100, 100, 100, 100], [120]]
groups[0,groups.index(groups.sort { |a,b| a.count <=> b.count }.last)].flatten.count
# => 14
Using regex, it can be precise and simple.
Upvotes: 1
Reputation: 172
my_array.index.with_index{|value,index| my_array[index,6].uniq.size==1}
This is a kind of tweak, if you mean "optimised" just in the way code looks like.If you mean optimised performance. it does not fit.
Upvotes: 2