2013-02-03 198 views
0

我有以下數組,我試圖按比分排序,然後匹配,然後名稱,但我的方法不工作。任何人都能看到爲什麼按子數組排序多維數組

最終順序應該是4,3,5,

usort我用的是在底部。

 [3] => Array 
      (
       [name] => DrayTek Vigor 2130Vn VoIP/WiFi Router 
       [matches] => Array 
        (
         [0] => voip 
        ) 
       [score] => 3 
      ) 
     [4] => Array 
      (
       [name] => DrayTek Vigor 2750n VDSL Wireless Router 
       [matches] => Array 
        (
         [0] => 2750 
        ) 
       [score] => 3 
      ) 
     [5] => Array 
      (
       [name] => DrayTek Vigor 2850Vn VDSL/ADSL VoIP Router 
       [matches] => Array 
        (
         [0] => voip 
        ) 
       [score] => 3 
      ) 

邏輯

1. all have the same score, so no change in order 
2. 4 has 2750 in matches[0] which assuming numbers come before letters, moves 4 up 
** the order now should be 4,3,5 
3. as 3 and 5 have the same matches[], no change in order 
4. 3's name naturally comes before 5 but since its already above, no change 
** final order should be 4,3,5 

排序結果,得分最高的第一個,接着匹配數組,然後命名

function cmp($a, $b) 
{ 
    if ($a['score'] < $b['score']) 
     return 1; 
    elseif ($a['score'] > $b['score']) 
     return -1; 
    elseif (! array_diff($a['matches'], $b['matches'])) 
     return 1; 
    elseif (! array_diff($b['matches'], $a['matches'])) 
     return -1; 
    elseif (($c = strnatcmp(strtolower($a['name']), strtolower($b['name']))) !== 0) 
     return $c; 
    else 
     return 0; 
} 
usort($this->results['rows'], "cmp"); 
+0

我不明白你試圖用火柴數組排序該怎麼辦... –

+0

@馬克 - 我想組「匹配」陣列在一起。由於3和5都具有相同的分數並與數組匹配,因此它們應該一個接一個出現,但它們之間用4分隔。 – Christian

+0

仍然沒有得到它。 2750爲什麼擊敗voip? –

回答

0

你似乎有逆轉了比賽陣列比較的感覺(你回來1,如果它們相等,而不是返回0 /讓它通過下一個測試)。因爲你需要一個明確的秩序時,他們不相等,也許你應該排序的匹配數組的長度:

function cmp($a, $b) 
{ 
    # sort by score 
    $result = $b['score'] - $a['score']; 

    # then by number of matches 
    if ($result == 0) { 
     $result = count($b['matches']) - count($a['matches']); 
    } 

    # if they have the same number of matches but different matches, who wins? 
    if ($result == 0) { 
     $result = strnatcasecmp($a['name'], $b['name']); 
    } 

    return $result; 
} 

的問題array_diff是,它返回一個單一的陣列。你將這個結果與a和b的排序進行比較是什麼?比較函數需要能夠排列任何兩個項目,而不需要其他任何上下文。

+0

不應該被計數($ b ['matches']) - count($ a ['matches']);因爲它們是數組。加上所有3有相同數量的元素,所以不會改變訂單 – Christian

+0

@Christian - 感謝您的錯字修復。重要的是,如果數組是相同的,那麼你返回1,這是錯誤的。比較函數返回0表示相等,-1表示a

+0

我假設你的意思是'! array_diff($ a ['matches'],$ b ['matches'])'這實際上是說'如果a完全在b然後是false',並且後面的行檢查b是否完全在a中則返回false – Christian

0

找到了解決辦法

function cmp($a, $b) 
{ 
    if ($a['score'] < $b['score']) 
     return 1; 

    if ($a['score'] > $b['score']) 
     return -1; 

    if (count($a['matches']) > count($b['matches'])) 
     return 1; 

    if (count($a['matches']) < count($b['matches'])) 
     return -1; 

    natsort($a['matches']); natsort($b['matches']); 

    for ($i = 0; $i < count($a['matches']); $i++) 
    { 
     if (($c = strnatcasecmp($b['matches'][$i], $a['matches'][$i])) !== 0) 
      return $c; 
    } 

    if (($c = strnatcasecmp(strtolower($a['name']), strtolower($b['name']))) !== 0) 
     return $c; 

    return 0; 
} 

usort($this->results['rows'], "cmp"); 
+0

如果它解決了你的問題,你應該接受你自己的答案,這樣問題就不會被打開。你知道那些'natsort'調用實際上改變了源數組,對嗎? –

+0

@馬克 - 它給了我一個警告,我不能接受我自己的答案在另一天。它改變順序並不重要,但有更快的選擇嗎? – Christian