【问题标题】:Numeric sort an array with mixed types values对具有混合类型值的数组进行数字排序
【发布时间】:2011-12-18 19:57:08
【问题描述】:

我有一个这样的混合数组:

$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

请解释一下为什么要这样排序?

【问题讨论】:

  • 混合数组实际上包含什么?可能有一种方法可以将数字和字符串数据分开。
  • 这个问题是我对 sort() 函数的好奇

标签: php arrays sorting


【解决方案1】:

基本上它应该从 A 到 Z 排序,然后按数字顺序,但是使用混合类型的函数不知道如何对数组进行排序并给出随机结果...

在手册页中有一个巨大的警告说:

对具有混合类型值的数组进行排序时要小心,因为 sort() 会产生不可预知的结果。

你可以给函数添加一个参数:

  • SORT_REGULAR - 正常比较项目(不要更改类型)

  • SORT_NUMERIC - 以数字方式比较项目

  • SORT_STRING - 将项目作为字符串进行比较

  • SORT_LOCALE_STRING - 根据当前语言环境将项目作为字符串进行比较。在 PHP 4.4.0 和 5.0.2 中添加,它使用系统语言环境,可以使用 setlocale() 更改。

根据php.net上的手册here

编辑 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 代码,而 L 在 a b l 之前... 121 排在第一位,因为你把它写成字符串"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”混淆
  • 是的,我编辑了帖子,在手册页中有一个关于排序混合类型数组的明确警告,可能会导致不可预知的结果,我认为是因为函数不知道如何对数组进行排序(按字符串或按数字顺序)
  • 可能对该数组进行排序的最佳方法是使用标志SORT_REGULAR,但它本身会给出一个奇怪的结果,因为它不会正确排序字符串(Lemonapple 之前和lemon) 之前由于 ascii 字符值...
  • 我认为 SORT_REGULAR 是按 ASCII 表排序的。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    我相信使用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
    )
    ?>
    

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 2021-02-10
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 2014-08-03
      • 2020-01-05
      相关资源
      最近更新 更多