开发者

Ruby: Compare two arrays for matches, and order results in DESC order

开发者 https://www.devze.com 2023-02-11 14:01 出处:网络
I have a user model. Each user has restaurant names associated with them. I have a view (index.html.erb) which shows all users.

I have a user model. Each user has restaurant names associated with them. I have a view (index.html.erb) which shows all users.

I want to order the users in this view based on how many restaurants the current_user and some other user have in common in descending order... (it does the opposite!)


ex.

User1 (current_user) has been to McDonalds, Burger King, Arby'开发者_如何学Cs

User2 has been to Ivar's

User3 has been to McDonalds, Burger King


When User1 loads the index view, the order the users should be displayed is:

User1 (3/3 restaurants match)

User3 (2/3 restaurants match)

User2 (0/3 restaurants match)


my User.rb file

def compare_restaurants
  self.restaurants.collect
end

my users_controller.rb

def index
  @users = User.all.sort_by {|el| (el.compare_resturants & current_user.compare_resturants).length }
end


If you're dead set on using sort_by then you can just negate the numbers:

def index
  @users = User.all.sort_by { |el|
    -(el.compare_resturants & current_user.compare_resturants).length
  }
end

This trick only works because you're sorting by numeric values. If you were sorting on strings then you'd have to use something like this:

reverse_sorted = a.sort_by { |x| something(x) }.reverse

but that would involve an extra copy of the array and the extra work that reverse would do. In such cases you should use a full sort with reversed comparison logic.

If you're were trying to use sort_by to avoid computing something expensive for each comparison and you were sorting on something non-numeric, then you could always use sort with an explicit Schwartzian Transform to compute the expensive things only once.


Just sort them in the controller.

my = User.find_by_id this_user  # Or however you're getting "the current user"
@users = User.all.-([my]).sort do |a, b|
  common_with_a = (my.restaurants & a.restaurants).length
  common_with_b = (my.restaurants & b.restaurants).length
  common_with_a <=> common_with_b
end

... but if you're planning on letting the user start sorting various columns or reversing the sorting a lot, you should implement your sort in Javascript so you can cut down on the number of page reloads and subsequent database hits you have to make.

0

精彩评论

暂无评论...
验证码 换一张
取 消