2016-04-07 23 views
1

我想根據他們有多少朋友給予我的玩家獎金。在沒有經過整個範圍的情況下找到範圍之間的值

我有斷點(例如0,1,5,10,25)

爲0個朋友,他得到0獎金。

爲1樓的朋友,他得到1000,爲5或2000等以上...

我現在做的是這樣的:

public function getFriendsBonusByFriendsAmount($amount) 
{ 
    switch (true) { 
     case ($amount < 1): 
      return 0; 
     case ($amount < 5): 
      return 1000; 
     case ($amount < 10): 
      return 2000; 
     case ($amount < 25): 
      return 3000; 
     case ($amount >= 25): 
      return 5000; 
    } 
} 

我正在尋找一種不同的方式來找到沒有foreach /開關的獎金

也許想到一個數組或陣列,我可以玩?

$bonusBreakpoints = [ 
    0 => 0, 
    1 => 1000, 
    5 => 2000, 
    10 => 3000, 
    25 => 5000 
] 

或者也許兩個數組有相應的索引嗎?

我想到了一個辦法做到這一點,但它是一個浪費內存:

$bonusPerFriends = [ 
    0 => 0, 
    1 => 1000, 
    2 => 1000, 
    3 => 1000, 
    4 => 1000, 
    5 => 2000, 
    6 => 2000, 
    ... 
    25 => 5000 
] 

我寧可不使用這種方式。

+0

我認爲最好的是將這個值存儲在數據庫中。當你進行SQL查詢時,你可以爲一個用戶獲得很好的價值。 (類似於'where user = 1 and friend = 5') – Xenofexs

+0

如果你正在製作'a> x> b',即總是在一個範圍內檢查值,那麼你必須在每個範圍之間刻錄...因爲你可以在一次超過一個範圍 – Bonatti

+0

@Bonatti在這種情況下,你不能在同一個範圍內兩次。 0,1-4,5-14,15-24,25 + –

回答

0

閱讀答案和更多的研究後,我得出結論說,二進制搜索是我最好的選擇。

的數據應該看起來有點像這樣:

$bonuses = [ 
    [ 'min' => 0, 'max' => 0, 'amount' => 0 ] 
    [ 'min' => 1, 'max' => 4, 'amount' => 1000 ] 
    [ 'min' => 5, 'max' => 14, 'amount' => 2000 ] 
    ... 
    [ 'min' => 25, 'max' => PHP_INT_MAX, 'amount' => 5000 ] 
] 

你開始在count($bonuses)/2,並從那裏檢查你是否是分以下,如此去一半,否則檢查,如果你是以上max和去中途在那裏。其他...只是返回獎金因爲你是在正確的範圍之間。

由於我的大多數用戶沒有任何朋友或超過25我可能會首先檢查第一個和最後一個單元格。

0

@ andrey-mischenko的答案在技術上是正確的,但並沒有解決問題沒有foreach,就像你在你的問題中說的那樣。(編輯:答案刪除)試試這個:

$bonusBreakpoints = [ 
    0 => 0, 
    1 => 1000, 
    5 => 2000, 
    10 => 3000, 
    25 => 5000 
]; 

$justTheKeys = array_keys($bonusBreakpoints);  

public function getFriendsBonusByFriendsAmount($amount) 
{ 
    $bonus = array_reduce($justTheKeys, function($carryOver, $item) use ($amount) 
     { 
      if ($amount >= $item) return $bonusBreakpoints($item); 

      return $carryOver; 
     } 
    return $bonus; 
} 

(我知道,這不是什麼array_reduce原本打算我明白了一個問題,一記遊戲像「找到創造性的辦法。從明顯的人除了解決這個問題,比如環路或開關。」如果我不得不爲工作代碼這一點,我會probabely使用循環了。:))

+0

不是太破舊,但也不優雅。 我仍然寧願保存範圍,並使用二進制搜索來避免循環比這個解決方案。問題是,哪個php函數使用二進制搜索.. –

+0

沒有原生的,afaik ...這是一個很好的示例實現,既遞歸又迭代:http://infopotato.com/blog/index/binary_search –

0

嗯,有時候foreach/switch最好解決方案:)

/** 
* Calculates bonus based on how many 
* friends the player have from predefined breakpoints 
**/ 
function getBonus($friends) { 
    $bonuses = [0, 1000, 2000, 3000, 5000]; 
    $stops = [[PHP_INT_MIN, 0], [1, 4], [5, 14], [15, 24], [25, PHP_INT_MAX]]; 

    // replace the stops by bonus if match, otherwise return empty - O(n) 
    $bonus = array_map(function ($stop, $bonus) use ($friends) { 
     if ($friends >= $stop[0] && $friends <= $stop[1]) { 
      return $bonus; 
     } 
    }, $stops, $bonuses); 

    // clean up the array from empty values - O(n) 
    $bonus = array_filter($bonus , 'is_numeric'); 

    // from array(3 => 3000) to 3000 - O(1) 
    return array_pop($bonus); 
} 

結果:

echo getBonus(0).PHP_EOL; // 0 
echo getBonus(4).PHP_EOL; // 1000 
echo getBonus(12).PHP_EOL; // 2000 
echo getBonus(20).PHP_EOL; // 3000 
echo getBonus(39).PHP_EOL; // 5000 

附: $bonuses$stops這裏必須等長。

+0

@RyanVincent用'array_reduce'我需要改變獎金/停止邏輯,而我不喜歡這兩個變種...(剛開始用'array_map') – alquist42

+0

不是在批評 - 真的只是好奇 - 我可能會使用array_reduce - 沒有'一個真正的方法':)將很快刪除我的評論 –

+1

@RyanVincent同意'array_reduce'並同意沒有'一個真正的方式'! – alquist42

相關問題