In Ruby, What Is the Cleanest Way of Obtaining the Index of the Largest Value in an Array

In Ruby, what is the cleanest way of obtaining the index of the largest value in an array?

For Ruby 1.8.7 or above:

a.each_with_index.max[1]

It does one iteration. Not entirely the most semantic thing ever, but if you find yourself doing this a lot, I would wrap it in an index_of_max method anyway.

How do I find the index of the maximum value of an array?

If you want to omit nils from the result, then you can use:

array.index(array.compact.max)

Or if you wish to treat nils like zeros, then first convert them to Floats:

array.index(array.map(&:to_f).max)

In the event of a tie, this will return the index of the first max value. You could also get the last index with Array#rindex.

I'm trying to do a stock picker method on Ruby but i have some issue in my code

Another option is to slice the Array while iterating over it for finding the best profit:

res = ary.each_with_index.with_object([]) do |(buy_val, i), res|
highest_val = ary[i..].max
highest_idx = ary[i..].each_with_index.max[1] + i
res << [highest_val - buy_val, i, highest_idx]
end.max_by(&:first)

#=> [12, 1, 4]

Where 12 is the profit, 1 is the buy index and 4 is the sell index.


To understand how it works, run this extended version, it worth more than any written explanation:

res = []
ary.each_with_index do |buy_val, i|
p buy_val
p ary[i..]
p highest_val = ary[i..].max
p highest_idx = ary[i..].each_with_index.max[1] + i
res << [highest_val - buy_val, i, highest_idx]
p '----'
end

res #=> [[0, 0, 0], [12, 1, 4], [9, 2, 4], [6, 3, 4], [0, 4, 4], [2, 5, 8], [4, 6, 8], [9, 7, 8], [0, 8, 8]]

From the Ruby standard library I used Enumerable#each_with_index, Enumerable#each_with_object, Enumerable#max and Enumerable#max_by.


For getting the index of the max I kindly stole from Chuck (https://stackoverflow.com/a/2149874), thanks and +1. I didn't look for any better option.

As per a comment from Cary Swoveland in the linked post:

[..] a.index(a.max) will return the index of the first and
a.each_with_index.max[1] will return the index of the last [..]

So, maybe you want to use the first option to keep the time between buy and sell shorter.

What is the right way to iterate through an array in Ruby?

This will iterate through all the elements:

array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }

# Output:

1
2
3
4
5
6

This will iterate through all the elements giving you the value and the index:

array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }

# Output:

A => 0
B => 1
C => 2

I'm not quite sure from your question which one you are looking for.

How to sort only specific elements in an array?

Possible solution

ary = [3, "foo", 2, 5, "bar", 1, "baz", 4]

integers = ary.select(&->(el) { el.is_a?(Integer) }).sort
ary.map { |n| n.is_a?(Integer) ? integers.shift : n }

# => [1, "foo", 2, 3, "bar", 4, "baz", 5]

Ruby find in array with offset

Cleaner is here obviously subjective matter. If you aim for short, I don't think you could do better than that. If you want to be able to chain multiple such finds, or you are bothered by slicing, you can do something like this:

module Enumerable
def find_multi *procs
return nil if procs.empty?
find do |e|
if procs.first.call(e)
procs.shift
next true if procs.empty?
end
false
end
end
end

a = (1..10).to_a
p a.find_multi(lambda{|e| e % 5 == 0}, lambda{|e| e % 3 == 0}, lambda{|e| e % 4 == 0})
#=> 8

Edit: And if you're not concerned with the performance you could do something like:

array.drop_while{|element|
!element.meets_some_criterion?
}.drop(1).find{|element|
element.meets_another_criterion?
}

Return the index of the max number in a 2d array of ints in Ruby

First you get the max value:

m = arr.flatten.max
#=> 99

Then it sounds like you either want the index of the array containing m:

arr.index{|x| x.include? m}
#=> 0

or that index plus m's index in that array

[i = arr.index{|x| x.include? m}, arr[i].index(m)]
#=> [0, 0]

Extracting multiple entries of a Ruby array

array.values_at(3,1,6) #=> ["d","b","g"]


Related Topics



Leave a reply



Submit