Counting distinct and duplicate attribute values in an array
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 m开发者_开发百科ust I modify the code so that the correct rank is returned, and not just the value of the index position?
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
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
精彩评论