3

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 
7
  • 1
    What is your definition of array getting normalised? Commented Jan 14, 2019 at 11:07
  • @ray same elements starts appearing. Commented Jan 14, 2019 at 11:11
  • 1
    @Aparichith "same elements starts appearing" is a bit vague. That almost sounds like "you'll know it when you see it". Be more specific, please. Commented Jan 14, 2019 at 11:23
  • @Stefan We can define function for finding starting index of longest repeating number sequence but it does not define it normalised. Commented Jan 14, 2019 at 11:25
  • "Can anyone suggest me [a] more [...] correct way" – what's wrong with your approach? Commented Jan 14, 2019 at 11:28

4 Answers 4

2
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.

Sign up to request clarification or add additional context in comments.

2 Comments

can you elaborate how number 6 works here? seems it will not work for other combinations of integers.
The question has been changed. This answer is based on the demonstration code.
1

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.

Comments

1

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.

Comments

1
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.