2013-02-03 197 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