0

I have a 2D array:

[["user1", 20], ["user2", 30], ["user3", 10]] 

The first element of a subarray is the username, and the second one its score.

I need to return the username with the maximum score. For example, here it would return "user2".

Either one user has a higher score, or they all have the same score (in which case it should return "all").

I know how to do this with a bunch of iterations and many lines of code, but I'm trying to find the "best practice way".

What would you advise ?

Graham Slick
  • 6,692
  • 9
  • 51
  • 87
  • 1
    What's a `user` in this context - `["user1", 20]` or `"user1"`? And is a user's number the number within the string (i.e. `1` in `"user1"`) or the second element (i.e. `20` in `["user1", 20]`)? That being said, I would advice to use a custom `User` class with attributes `:name` and `:number` or at least a hash instead of an array. – Stefan Jan 10 '16 at 11:51
  • the first element of a subarray is the username, and the second one its score. The number is the second element of the subarray. – Graham Slick Jan 10 '16 at 12:11
  • 1
    Maybe because the question was unclear or because you didn't include your own attempt. – Stefan Jan 10 '16 at 12:18
  • 1
    What the expected result if there is more than one maximum score? – Stefan Jan 10 '16 at 12:20
  • @Stefan thanks, edited it – Graham Slick Jan 10 '16 at 12:26

2 Answers2

6

Check out max_by

users = [["user1", 20], ["user2", 30], ["user3", 10]]

users.max_by{ |user, weight| weight }
#=> ["user2", 30]

# shorthand
users.max_by(&:last)
#=> ["user2", 30]

users.max_by(&:last).first
#=> "user2"

It worth to be mentioned that if you have a number of maximums it will return only first one.

Stefan
  • 109,145
  • 14
  • 143
  • 218
fl00r
  • 82,987
  • 33
  • 217
  • 237
1

Simple solution for the given example:

a = [["user1", 20], ["user2", 30], ["user3", 10]]
h = Hash[a].invert
h[h.keys.max]
#=> "user2"

In the general case, where identical maximum numbers will occur, the following solution will return all users sharing the same maximum value (w/ invert function by Nigel, see Swapping keys and values in a hash):

class Hash
  def safe_invert
    self.each_with_object( {} ) { |(key, value), out| ( out[value] ||= [] ) << key }
  end
end

a = [["user1", 20], ["user2", 30], ["user3", 10], ["user4", 30]]
h = Hash[a].safe_invert
h[h.keys.max]
#=> ["user2", "user4"]
Community
  • 1
  • 1
bogl
  • 1,864
  • 1
  • 15
  • 32