views:

46

answers:

2

I have an array of users that's sorted in descending order based on total_points.

I need to find the rank of each user in that array. The issue is that more than one user can have the same total points and, thus, the same rank. For example, three users could be in 3rd place with 200 Points. Here's my current code:

class Leader < ActiveRecord::Base  
  def self.points_leaders
    all_leaders = all_points_leaders # returns array of users sorted by total_points in desc order
    all_leaders_with_rank = []

    all_leaders.each do |user|
      rank = all_leaders.index(user)+1
      all_leaders_with_rank << Ldr.new(rank, user) # Ldr is a Struct
    end

    return all_leaders_with_rank
  end
end

How must I modify the code so that the correct rank is returned, and not just the value of the index position?

A: 

The borderline-brute-force approach would be a simple change to your existing code.

rank = 1
all_leaders.each_with_index do |user, idx|
  # If this user has a different point total than the previous user in the list,
  # bump the rank.
  if idx > 0 && all_leaders[idx - 1].total_points != user.total_points
    # The point of using the idx as an offset here is so that you end up with 
    # T1
    # T1
    # T3
    # in the case of a tie for first.
    rank = idx + 1
  end
  all_leaders_with_rank << Ldr.new(rank, user) # Ldr is a Struct
end
jdl
A: 

Create an array of unique points (sorted by the all_points_leaders function). Use the index + 1 of that array as the rank of the user.

def self.points_leaders
  all_points = all_points_leaders.map {|user| user.total_points }.uniq
  all_points_leaders.map do |user|
    rank = all_points.index(user.total_points) + 1
    Ldr.new(rank, user)
  end
end
Laz