可能应该记录的一件事是,natsort 和 natcasesort 都维护了数组的键值关联。如果您对数字索引的数组使用 natsort,则 for 循环不会产生排序顺序;但是,foreach 循环会产生排序顺序,但索引不会按数字顺序排列。如果您希望 natsort 和 natcasesort 打破键值关联,只需在排序数组上使用 array_values,如下所示
natcasesort($arr);
$arr = array_values($arr);
(PHP 4, PHP 5, PHP 7, PHP 8)
natcasesort — 使用不区分大小写的“自然顺序”算法对数组进行排序
natcasesort() 是 natsort() 的不区分大小写版本。
此函数实现了一种排序算法,该算法以人类的方式对字母数字字符串进行排序,同时保持键值关联。这被称为“自然排序”。
注意:
如果两个成员比较为相等,它们将保留其原始顺序。在 PHP 8.0.0 之前,它们在排序数组中的相对顺序是未定义的。
注意:
将数组的内部指针重置为第一个元素。
array
输入数组。
始终返回 true
。
示例 #1 natcasesort() 示例
<?php
$array1 = $array2 = array('IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png');
sort($array1);
echo "标准排序\n";
print_r($array1);
natcasesort($array2);
echo "\n自然顺序排序(不区分大小写)\n";
print_r($array2);
?>
以上示例将输出
Standard sorting Array ( [0] => IMG0.png [1] => IMG3.png [2] => img1.png [3] => img10.png [4] => img12.png [5] => img2.png ) Natural order sorting (case-insensitive) Array ( [0] => IMG0.png [4] => img1.png [3] => img2.png [5] => IMG3.png [2] => img10.png [1] => img12.png )
有关更多信息,请参见:Martin Pool 的 » 自然顺序字符串比较 页面。
可能应该记录的一件事是,natsort 和 natcasesort 都维护了数组的键值关联。如果您对数字索引的数组使用 natsort,则 for 循环不会产生排序顺序;但是,foreach 循环会产生排序顺序,但索引不会按数字顺序排列。如果您希望 natsort 和 natcasesort 打破键值关联,只需在排序数组上使用 array_values,如下所示
natcasesort($arr);
$arr = array_values($arr);
按任意顺序排序 UTF-8
<?php
mb_internal_encoding("UTF-8");
class utf_8_german
{
// 其他所有元素都在最后排序
static $order = '0123456789AaÄäBbCcDdEeFfGgHhIiJjKkLlMm
NnOoÖöPpQqRrSsßTtUuÜüVvWwXxYyZz';
static $char2order;
static function cmp($a, $b) {
if ($a == $b) {
return 0;
}
// 延迟初始化映射
if (empty(self::$char2order))
{
$order = 1;
$len = mb_strlen(self::$order);
for ($order=0; $order<$len; ++$order)
{
self::$char2order[mb_substr(self::$order, $order, 1)] = $order;
}
}
$len_a = mb_strlen($a);
$len_b = mb_strlen($b);
$max=min($len_a, $len_b);
for($i=0; $i<$max; ++$i)
{
$char_a= mb_substr($a, $i, 1);
$char_b= mb_substr($b, $i, 1);
if ($char_a == $char_b) continue;
$order_a = (isset(self::$char2order[$char_a])) ? self::$char2order[$char_a] : 9999;
$order_b = (isset(self::$char2order[$char_b])) ? self::$char2order[$char_b] : 9999;
return ($order_a < $order_b) ? -1 : 1;
}
return ($len_a < $len_b) ? -1 : 1;
}
}
// 使用示例:
$t = array(
'Birnen', 'Birne', 'Äpfel', 'Apfel',
);
uasort($t, 'utf_8_german::cmp');
echo '$t: <pre>'.htmlspecialchars(print_r($t,true),null,'UTF-8').'</pre>';
?>
这是一个函数,它将根据包含特殊字符的键对数组的键进行自然排序。
<?php
function natksort($array)
{
$original_keys_arr = array();
$original_values_arr = array();
$clean_keys_arr = array();
$i = 0;
foreach ($array AS $key => $value)
{
$original_keys_arr[$i] = $key;
$original_values_arr[$i] = $value;
$clean_keys_arr[$i] = strtr($key, "ÄÖÜäöüÉÈÀËëéèàç", "AOUaouEEAEeeeac");
$i++;
}
natcasesort($clean_keys_arr);
$result_arr = array();
foreach ($clean_keys_arr AS $key => $value)
{
$original_key = $original_keys_arr[$key];
$original_value = $original_values_arr[$key];
$result_arr[$original_key] = $original_value;
}
return $result_arr;
}
?>
希望对某些人有用:)
Ulli at Stemmeler dot net: 我重做了你的函数——现在更紧凑了——享受吧...
function ignorecasesort(&$array) {
/* 使每个元素成为其小写自身加上自身 */
/* (例如,“MyWebSite” 将变为“mywebsiteMyWebSite” */
for ($i = 0; $i < sizeof($array); $array[$i] = strtolower($array[$i]).$array[$i], $i++);
/* 对其进行排序——仅使用小写版本 */
sort($array);
/* 获取每个数组元素,将其一分为二,并将后半部分添加到一个新数组中 */
/* (例如,“mywebsiteMyWebSite” 将变为“MyWebSite”) */
for ($i = 0; $i < sizeof($array); $i++) {
$this = $array[$i];
$array[$i] = substr($this, (strlen($this)/2), strlen($this));
}
}
我一直使用 natcasesort 和 sort 对混合数组(根据描述)得到不同的结果。
有时简单更好
一小段代码
<?php if($responders->num_rows) {
$i=0;
while($row= $responders->fetch_assoc()) {
$user=getUserName($row['responderID']);
$r[$i]= array("sortname"=>strtolower($user),"userName"=>$user, "userID"=>$row['responderID'], "responderID"=>$row['idresponders']);
$i++;
}
sort($r);
print_r($r);
}
?>
我只是在结果集的前面创建了一个小写排序字段,然后按它进行排序——这提供了预期结果并保持实际所需字段不变。
对于好奇的人来说:出于安全原因,所有用户信息都保存在与内容数据库不同的另一个数据库(和表)中。我们编写的 getUser 函数允许我们仅提取法律允许的内容,而不会暴露任何其他内容。
这就是为什么没有使用左连接或其他方法,我们必须在这里从两个数据库构建一个伪结果数组。
如果您希望具有相同第一个字符的项目以较短字符串先出现的顺序列出,请将此循环添加到上面的函数中。
--------------------
/* 较短的字符串放在较长的字符串之前(例如,“abc” 应该放在“abcd” 之前) */
for($i=count($array)-1;$i>0;$i--) {
$str_a = $array[$i ];
$str_b = $array[$i-1];
$cmp_a = strtolower(substr($str_a,0,strlen($str_a)));
$cmp_b = strtolower(substr($str_b,0,strlen($str_a)));
if ($cmp_a==$cmp_b && strlen($str_a)<strlen($str_b)) {
$array[$i]=$str_b; $array[$i-1]=$str_a; $i+=2;
}
}
--------------------