简体   繁体   中英

in ruby how do I add objects to an array, keep a counter for every object and still check easily if the object is in the array?

I want to compile a list of recommended friends.

What I was thinking was something like this (this is semi pseudo (sudo) code!):

recommended_friends = []
friends.each do |friend|
   while recommeded_friends.length < 10
      friend.friends.each do |friend|
         if friend.in?(recommeded_friends)
             recommeded_friends[friend][counter] += 1
         else
             recommeded_friends << [friend, 0]
         end
      end
    end
end

But this obviously doesn't work. How would you guys approach this?

Thanks for any suggestions.

The tables (some are shortened):

Users:
id | name 

Friendships
id | user_1_id | user_2_id | requested_at | accepted_at | declined_at |

A friendship between user1 and user2 only occurs once in the DB.

UPDATED. Try something like this, it should work:

recommended_friends = {}
friends.each do |friend|
   if recommeded_friends.length < 10
      friend.friends.each do |other_friend|
         if other_friend != this_user          # exclude myself 
           recommeded_friends[other_friend] =
             (recommeded_friends[other_friend] | 0) + 1
         end
      end
   end
end
recommendend_friends.sort_by{|key, value| value}.reverse
top_ten = recommended_friends.first(10).map{|a| a[0]}

SQL version:

Users.find_by_sql([
  "SELECT u.*
   FROM 
   (SELECT f2.id, f2.user_1_id u_1_id, f2.user_2_id u_2_id, (count(f1.id)) cnt
      FROM friendships f1 
      JOIN friendships f2 ON f1.user_1_id = f2.user_1_id
                          OR f1.user_2_id = f2.user_1_id
                          OR f1.user_2_id = f2.user_2_id
                          OR f1.user_1_id = f2.user_2_id
      WHERE (f1.user_1_id = ? OR f1.user_2_id = ?)
        AND (f2.user_1_id <> ? AND f2.user_2_id <> ?)
      GROUP BY f2.id, f2.user_1_id, f.user_2_id
      HAVING count(f2.id) = 1
      ORDER BY cnt DESC) fs
   JOIN friendships ff ON ff.user_1_id = fs.u_1_id
                       OR ff.user_2_id = fs.u_1_id
                       OR ff.user_2_id = fs.u_2_id
                       OR ff.user_1_id = fs.u_2_id
   JOIN users u ON 
     CASE WHEN (ff.user_1_id = fs.u_1_id OR ff.user_2_id = fs.u_1_id) 
                THEN fs.u_2_id ELSE fs.u_1_id END = u.id ", 
 user.id, user.id, user.id, user.id]).first(10)

In theory it should work, take a try.

recommeded_friends will always stay an empty array. You can not do this: recommeded_friends < 10

Try this: recommeded_friends.length < 10

The simplest method I can think of:

 recommended_friends = friend.friends.sort do |a,b|
   a <=> b # insert your ranking algorithm here
 end.take 10

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM