2013-02-24 58 views
0

我創建了一個選擇用戶的算法,由於它在無盡滾動網頁上使用,所以運行速度比我想要的要慢。加速我的Ruby代碼

我不太瞭解Ruby,以確定如何提高效率。有沒有人有任何想法?

def gen_users(list_length) 
new_selection = [] 

# get all users 
all_users = User.all 

# shuffle them randomly 
shuffled_users = all_users.shuffle 

# cycle through all users randomly 
shuffled_users.each do |user| 
    # check user profile isn't already in current selection 
    if [email protected]?(user) 
    # check user profile exists 
    if user.etkh_profile 
     profile_completeness = user.etkh_profile.get_profile_completeness 

     # check user profile meets minimum requirements   
     if profile_completeness >= MIN_PROFILE_COMPLETENESS && user.avatar? \ 
     && user.etkh_profile.background.length >= MIN_BACKGROUND_LENGTH 

     # insert randomness and bias towards profiles with high completeness 
     r = Random.new 
     rand = r.rand(1..10) # random integer between 1 and 10 
     product = rand * profile_completeness 

     # threshold is defined by the probability that a profile with min profile completeness 
     # will be selected 

     max_product = MIN_PROFILE_COMPLETENESS * 10 
     threshold = (1 - PROBABILITY_MIN_PROFILE) * max_product 

     if product >= threshold 
      # add to total list 
      @users << user 

      # add to list of latest selection 
      new_selection << user 
     end 
     end 
    end 
    end 

    # exit loop if enough users have been found 
    break if new_selection.length >= list_length 
end 

# return this selection 
return new_selection 
end 
+0

這樣的問題屬於http://codereview.stackexchange.com。有關更多信息,請參閱[常見問題](http://codereview.stackexchange.com/faq#im-confused-what-questions-are-on-topic-for-this-site)。 – 2013-02-24 17:25:03

回答

3

兩件事情你做錯了是:

  • threshold是恆定的。你不應該在循環中每次計算。
  • Random.new應該重複使用。這就是它的目的。每次循環中都不應該創建新的實例。

我的代碼(steenslag的改進引入)的重構(refactorization)會是這樣的:

THRESHOLD = (1 - PROBABILITY_MIN_PROFILE) * MIN_PROFILE_COMPLETENESS * 10 
RANDOM_GENERATOR = Random.new 

def gen_users(list_length) 
    (User.all - @users) 
    .select do |user| 
    profile = user.etkh_profile and 
    profile.background.length >= MIN_BACKGROUND_LENGTH and 
    (completeness = profile.get_profile_completeness) >= MIN_PROFILE_COMPLETENESS and 
    RANDOM_GENERATOR.rand(1..10) * completeness >= THRESHOLD 
    end 
    .select(&:avatar?) 
    .sample(list_length) 
    .tap{|a| @users.concat(a)} 
end 
+1

'sample(list_length)'而不是'shuffle.first(list_length)'? – steenslag 2013-02-24 16:58:09

+0

我放棄了。謝謝。 – sawa 2013-02-24 17:01:27

+0

哇,這幾乎是無法辨認......真的說明我是一個C/C++/C#程序員誰正在嘗試使用Ruby ... 它的工作原理除了它會拋出一個錯誤,如果用戶沒有etkh_profile。某種如果user.etkh_profile需要在profile.background.length之前 – 2013-02-24 17:33:58

0

這是很難說具體是什麼造成壞的表現,這取決於用戶,例如數。另外:

  1. max_productthreshold是常數,你並不需要計算他們每個週期。
  2. 也許user.etkh_profile是一個緩慢的方法?你每個週期調用三次。
  3. 此外,您不需要存儲大量數據的兩個局部變量(all_usersshuffled_users)。相反,你可以做一些像shuffled_users = User.all.shuffle