PHP:按其值的长度对数组进行排序?

68

我制作了一个字谜生成器,并且我有一个正匹配的数组。问题是它们的顺序都不同,我想能够对数组进行排序,使最长的数组值首先出现。

有人有任何关于如何做到这一点的想法吗?

12个回答

163
使用https://www.php.net/manual/en/function.usort.php,并结合这个自定义函数。
function sortByLength($a,$b){
    return strlen($b)-strlen($a);
}

usort($array,'sortByLength');

使用uasort如果你想保留旧的索引,使用usort如果你不在乎。
此外,我相信我的版本更好,因为usort是一种不稳定的排序方法。
$array = array("bbbbb", "dog", "cat", "aaa", "aaaa");
// mine
[0] => bbbbb
[1] => aaaa
[2] => aaa
[3] => cat
[4] => dog

// others
[0] => bbbbb
[1] => aaaa
[2] => dog
[3] => aaa
[4] => cat

16
这很好,但我不会仅称该函数为“sort”。下面的sortByLength更具描述性。 - Brian Kelly
11
提醒大家注意使用 mb_strlen() 函数,因为不同语言的字符串长度计算方式可能不同。 - Jeffz
1
不,Brian,这个函数的工作不是排序,而是比较。因此我会把它叫做compareStrLengthNegatively。 - fishbone
3
不将其命名为“sort”是很重要的,不是因为描述性,而是因为致命错误:无法重新声明sort。 - Don't Panic
2
为什么不使用mb_strlen而是strlen?虽然比strlen慢,但一旦出现多字节值,它将防止头痛。 - xZero
显示剩余3条评论

65
如果你想按照PHP 5.3的方式来做,你可能需要创建类似下面这样的东西:
usort($array, function($a, $b) {
    return strlen($b) - strlen($a);
});

这样做可以避免污染全局命名空间。但仅在源代码的单个位置需要时才这样做,以保持代码的DRY(不重复原则)。

45

PHP7即将到来。在PHP7中,您可以使用太空船操作符

usort($array, function($a, $b) {
    return strlen($b) <=> strlen($a);
});

希望这能在未来对你有所帮助。


2
有趣,我不知道那个。我想知道是否与@clttj建议的仅使用减法相比有任何性能优势。 - John

10
function sortByLength($a,$b){
  if($a == $b) return 0;
  return (strlen($a) > strlen($b) ? -1 : 1);
}
usort($array,'sortByLength');

2
这里有一个 bug。你的相等条件太狭窄了。字符串 "abc" 和 "def" 应该从这个排序中返回 0,但实际上不会。它们将返回 1。虽然我意识到这不是一个严重的错误(输出看起来不会出错),但技术上是不准确的。 - Peter Bailey
2
'if($a == $b) return 0;' 这是一个错误。我们讨论的是长度。 - Thinker
@ Peter 和 Thinker,是的,这是 PHP 手册中的一种怪异现象。我本人使用了 strlen($a) == strlen($b),但后来发现由于 PHP 使用不稳定排序,这并不重要!它仍然会弄乱顺序。因此,我想出了最短的可行函数。 - Unknown
从手册的一些示例中得到了这个(就像某人所说的那样),我并没有仔细分析它,因为我最近不太关注php,只是检查它是否有效。有更好的东西 - 很好。 - zalew
是的,手册中的示例和注释有时候很令人沮丧,但我不知道是否值得在意 :) 祝好。 - zalew

5

降序:

$array = ['aa', 'bb', 'c', 'ccc', 'a', 'ertre'];

usort($array, function($a, $b){
   return strlen($a) < strlen($b);
});

var_export($array);

// Output
array (
  0 => 'ertre',
  1 => 'ccc',
  2 => 'aa',
  3 => 'bb',
  4 => 'c',
  5 => 'a',
)

升序:

$array = ['aa', 'bb', 'c', 'ccc', 'a', 'ertre'];

usort($array, function($a, $b){
   return strlen($a) > strlen($b);
});

// Output
array (
  0 => 'c',
  1 => 'a',
  2 => 'aa',
  3 => 'bb',
  4 => 'ccc',
  5 => 'ertre',
)

为什么有人会使用这个,当在这个页面上5年前推荐了飞船运算符? - mickmackusa

1
array_multisort(array_map('count', $arr), SORT_DESC, $arr);

0

创建一个由你的数组元素的 strlen 组成的数组,并使用 multisort 对其进行排序。

foreach($Yourarray as $c=>$key) {               
    $key['maxlen'] = strlen($key);  
    $sort_numcie[] = $key['maxlen'];
}

array_multisort($sort_numcie, $Yourarray);  

这肯定会起作用。我很确定!


给一个值命名为$key是不直观的。在声明标量值为$key之后立即声明关联元素$key['maxlen']就很奇怪。$key['maxlen']实际上是一个无用的变量声明。 - mickmackusa

0

这里有一段代码片段,它清楚地说明了为什么你不应该在usort()内部使用函数调用——你将会不必要地对之前遇到的值进行strlen()调用。

在我的9个元素数组中,array_multisort()调用strlen() 9次,但是usort()调用strlen() 23次——这不太好。

代码:(演示)

function multisort($array) {
    array_multisort(array_map('strlen', $array), SORT_DESC, $array);
    printf(
        "Total strlen() calls: %d\n%s\n---\n",
        count($array),
        var_export($array, true)
    );
}

function usersort($array) {
    usort(
        $array,
        function($a, $b) {
            echo "strlen() called twice\n";
            return strlen($b) <=> strlen($a);
        }
    );
    var_export($array);
    echo "\n---\n";
}

multisort($array);
usersort($array);

输出(来自我的示例数组):

Total strlen() calls: 9
array (
  0 => 'eight',
  1 => 'seven',
  2 => 'three',
  3 => 'five',
  4 => 'four',
  5 => 'nine',
  6 => 'one',
  7 => 'six',
  8 => 'two',
)
---
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
strlen() called twice
array (
  0 => 'three',
  1 => 'seven',
  2 => 'eight',
  3 => 'four',
  4 => 'five',
  5 => 'nine',
  6 => 'one',
  7 => 'two',
  8 => 'six',
)
---

0

除了已接受的答案外,要按长度对数组进行排序,可以选择升序或降序

function strlen_compare($a,$b){
    if(function_exists('mb_strlen')){
         return mb_strlen($b) - mb_strlen($a);
    }
    else{
         return strlen($b) - strlen($a);
    }
}

function strlen_array_sort($array,$order='dsc'){
    usort($array,'strlen_compare');
    if($order=='asc'){
        $array=array_reverse($array);
    }
    return $array;
}

0

这里有一种使用太空船运算符的方法(需要 PHP 7.0):

$arr = ['apple','pear','oranges','banana'];
usort($arr, function ($a, $b) { return (strlen($a) <=> strlen($b)); });
print_r($arr);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接