Php 按子数组对多维数组排序

Php 按子数组对多维数组排序,php,sorting,Php,Sorting,我有下面的数组,我试图按分数、匹配、名称排序,但我的方法不起作用。有人知道为什么吗 最后的顺序应该是4,3,5 我使用的usort位于底部 [3] => Array ( [name] => DrayTek Vigor 2130Vn VoIP/WiFi Router [matches] => Array (

我有下面的数组,我试图按分数、匹配、名称排序,但我的方法不起作用。有人知道为什么吗

最后的顺序应该是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
            )
逻辑

对结果排序,首先是最高分,然后是匹配数组,然后是名称

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" );
函数cmp($a,$b)
{
如果($a['score']<$b['score'])
返回1;
elseif($a['score']>$b['score'])
返回-1;
elseif(!array_diff($a['matches'],$b['matches']))
返回1;
elseif(!array_diff($b['matches'],$a['matches']))
返回-1;
elseif($c=strnatcmp(strtolower($a['name'])),strtolower($b['name']))!==0)
返回$c;
其他的
返回0;
}
usort($this->results['rows',“cmp”);

您似乎对匹配数组比较有相反的感觉(如果它们相等,则返回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进行比较以获得排序?比较函数需要能够在没有任何其他上下文的情况下从数组的其余部分订购任意两项。

找到了解决方案

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" );
函数cmp($a,$b)
{
如果($a['score']<$b['score'])
返回1;
如果($a['score']>$b['score'])
返回-1;
如果(计数($a['matches'])>计数($b['matches']))
返回1;
如果(计数($a['matches'])results['rows',“cmp”);

我不明白您试图对matches数组排序做什么…@Mark-我正在尝试将“matches”数组分组在一起。因为3和5都有相同的分数和匹配数组,所以它们应该一个接一个地出现,但是它们被4隔开,仍然没有得到它。为什么2750击败了voip?@Mark-实际上,同一场比赛[]在一起比哪场比赛击败哪场比赛更重要。但为了回答你的问题,我想到了数字在字母之前的自然排序。我给这个问题增加了一些逻辑性。看看它是否对你有帮助。不应该是count($b['matches'])-count($a['matches']);因为它们是数组。加上所有3个元素都有相同数量的元素,所以不会改变order@Christian-谢谢你的排版。重要的是,如果数组相同,则返回1,这是错误的。比较函数返回0表示相等,-1表示a!数组_diff($a['matches'],$b['matches'])实际上是说“如果a完全在b中,则为false”,检查b是否完全在a中后的行则返回false不为false、“大于”或“小于”。但问题是,
array_diff
如果两个数组完全相等,则返回一个空数组,因此您的代码将返回1,并且永远不会进行下一次检查。如果解决了问题,您应该接受自己的答案,这样问题就不会悬而未决。你知道那些
natsort
调用实际上改变了源数组,对吗?@Mark-它给了我一个警告,我不能再接受我自己的答案了。实际上,它改变顺序并不重要,但有更快的选择吗?
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" );