混合类型值的数字排序数组

3
我有一个混合数组,例如:
$fruits = array(
    "lemon",
    "Lemon",
    20,
    "banana",
    "apple",
    "121",
    40,
    50
);

然后将其应用sort()函数,如下所示:

sort($fruits, SORT_NUMERIC);
foreach ($fruits as $key => $val) {
    echo "fruits[" . $key . "] = " . $val . "\n";
}

现在,我不理解的输出是:

fruits[0] = apple
fruits[1] = lemon
fruits[2] = banana
fruits[3] = Lemon
fruits[4] = 20
fruits[5] = 40
fruits[6] = 50
fruits[7] = 121

请解释为什么它排序方式是这样的?

混合数组“_actually_”包含什么?可能有一种方法可以分离数字和字符串数据。 - Bojangles
这个问题是关于sort()函数的,我只是出于好奇想了解一下。 - Ahmad Badpey
3个回答

3

OP,由于sort();函数对大写和小写字符的处理并不理想,为什么不将所有字符转换为小写后再进行排序呢?

<?php
$fruits = array("lemon","Lemon", 20, "banana", "apple","121",40,50);
$fruits = array_map("strtolower", $fruits); //using strtolower

sort($fruits );
foreach ($fruits as $key => $val) {
    echo "fruits[" . $key . "] = " . $val . "\n";
}
?>

输出

fruits[0] = 20
fruits[1] = 40
fruits[2] = 50
fruits[3] = 121
fruits[4] = apple
fruits[5] = banana
fruits[6] = lemon
fruits[7] = lemon

2
基本上,它应该按字母顺序从 A 到 Z 排序,然后按数字顺序排序,但是使用混合类型时,函数不知道如何对数组进行排序并给出随机结果......在手册页面中有一个巨大的警告说:
"当排序具有混合类型值的数组时要小心,因为 sort() 可能会产生不可预测的结果。"
你可以向函数添加一个参数:
- SORT_REGULAR - 正常比较项(不改变类型) - SORT_NUMERIC - 数值比较 - SORT_STRING - 字符串比较 - SORT_LOCALE_STRING - 基于当前区域设置将项目视为字符串进行比较。在 PHP 4.4.0 和 5.0.2 中添加,它使用系统区域设置,可以使用 setlocale() 进行更改。
根据 php.net 上的手册 这里 编辑 1: 可能您可以使用标志 SORT_REGULAR 获得最佳排序结果,因为它不会改变变量类型,数字仍然是数字,字符串仍然是字符串,但它也会给出奇怪的结果。
fruits[0] = 121
fruits[1] = Lemon
fruits[2] = apple
fruits[3] = banana
fruits[4] = lemon
fruits[5] = 20
fruits[6] = 40
fruits[7] = 50

我认为这是因为它比较了字符串中字母的ASCII码,而 La b l 之前... 你把它写成字符串 "121",所以它在第一位。 编辑2: 最好的方法是将类型分开:(这样PHP将把 "121" 视为数字而不是字符串,但你可以通过 if 条件语句轻松决定)。
<?php
$fruits = array("lemon","Lemon", 20, "banana", "apple","121",40,50);
$arr1=array();
$arr2=array();
      foreach($fruits as $key=>$val){
          if (is_numeric($val))
               array_push($arr1,$val); 
          else
              array_push($arr2,$val);
      }          
sort($arr1,SORT_NUMERIC);            
sort($arr2,SORT_LOCALE_STRING);
$fruits = array_merge($arr1,$arr2);
echo "<pre>";
foreach ($fruits as $key => $val) {
    echo "fruits[" . $key . "] = " . $val . "\n";
}
?>

无论排序标志是什么,它仍然会混淆“Lemon”和“lemon”。 - Mob
是的,我编辑了帖子,在手册页面中明确警告了对混合类型数组进行排序可能会导致不可预测的结果,我认为这是因为函数不知道如何按字符串或数字顺序对数组进行排序。 - Marcx
可能最好的排序数组的方法是使用标志 SORT_REGULAR,但它本身会产生奇怪的结果,因为它不会正确地对字符串进行排序(Lemonapplelemon 之前)由于 ASCII 字符值的原因... - Marcx
我认为SORT_REGULAR是按照ASCII表进行排序。 - johnlemon

1

我相信使用sort($array, SORT_NUMERIC),无法转换为数字的值将被视为0并以此方式排序。由于您示例中的所有字符串都变成了0,因此lemon是否在banana之前实际上并不重要。以下是一个例子:

<?php
$fruits = array("alpha", "bravo", -1, -0.001, 0, 0.001, 1, "x-ray", "zulu");
shuffle($fruits); // randomly re-arrange the items in array
sort($fruits, SORT_NUMERIC);
print_r($fruits);
// output -- pass 1
Array
(
    [0] => -1
    [1] => -0.001
    [2] => 0
    [3] => alpha
    [4] => x-ray
    [5] => zulu
    [6] => bravo
    [7] => 0.001
    [8] => 1
)
// output -- pass 2
Array
(
    [0] => -1
    [1] => -0.001
    [2] => bravo
    [3] => zulu
    [4] => 0
    [5] => x-ray
    [6] => alpha
    [7] => 0.001
    [8] => 1
)
// output -- pass 3
Array
(
    [0] => -1
    [1] => -0.001
    [2] => x-ray
    [3] => zulu
    [4] => 0
    [5] => bravo
    [6] => alpha
    [7] => 0.001
    [8] => 1
)
?>

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