【问题标题】:php array_multisort sorting columns i didnt ask to be sortedphp array_multisort 排序列我没有要求排序
【发布时间】:2018-10-27 08:39:35
【问题描述】:

我正在使用 array_multisort 按其中一列对多维数组进行排序。是的,我知道这个函数不需要只按一列排序,但这是用于可能有更多列被排序的代码,现在只有一个测试失败。

当我运行在互联网上找到的测试时,它运行良好。当我用其他一些测试数据运行几乎完全相同的东西时,它也在我没有要求它排序的列上排序。

此测试返回正确排序的数据(未排序的值):

$vc_array = array (
0 => array ('id' => 1,'name' => 'xyz','value' => 'abc','order' => 6),
 1 => array ('id' => 2,'name' => 'abc','value' => 'xyz','order' => 2),
 2 => array ('id' => 3,'name' => 'uvw','value' => 'ghi','order' => 1),
 3 => array ('id' => 4,'name' => 'def','value' => 'xyz','order' => 2,),
 4 => array ('id' => 5,'name' => 'ghi','value' => 'uvw','order' => 3),
 5 => array ('id' => 6,'name' => 'ghi','value' => 'def','order' => 3),
 6 => array ('id' => 7,'name' => 'ghi','value' => 'fff','order' => 3)
);

$vc_array_name = array_column($vc_array, 'name');

$out = array_multisort($vc_array_name, SORT_ASC, $vc_array);

var_dump($vc_array); // note the name 'ghi' and the order of the 'value' column.  the 'value' column has NOT been sorted, which is what is expected.

转储数据:

array(7) { [0]=> array(4) { ["id"]=> int(2) ["name"]=> string(3) "abc" ["value"]=> string(3) "xyz" ["order"]=> int(2) } [1]=> array(4) { ["id"]=> int(4) ["name"]=> string(3) "def" ["value"]=> string(3) "xyz" ["order"]=> int(2) } [2]=> array(4) { ["id"]=> int(5) ["name"]=> string(3) "ghi" ["value"]=> string(3) "uvw" ["order"]=> int(3) } [3]=> array(4) { ["id"]=> int(6) ["name"]=> string(3) "ghi" ["value"]=> string(3) "def" ["order"]=> int(3) } [4]=> array(4) { ["id"]=> int(7) ["name"]=> string(3) "ghi" ["value"]=> string(3) "fff" ["order"]=> int(3) } [5]=> array(4) { ["id"]=> int(3) ["name"]=> string(3) "uvw" ["value"]=> string(3) "ghi" ["order"]=> int(1) } [6]=> array(4) { ["id"]=> int(1) ["name"]=> string(3) "xyz" ["value"]=> string(3) "abc" ["order"]=> int(6) } }

此测试在“名称”字段上正确排序,但也在我没有请求的“数量”字段上排序,并且不希望对该列进行排序:

$objectListData4 =  [
        ["name" => "package", "quantity" => 1000, "color" => "brown"],
        ["name" => "box", "quantity" => 1000, "color" => "red"],
        ["name" => "notebook", "quantity" => 250, "color" => "orange"],
        ["name" => "pencil", "quantity" => 100, "color" => "yellow"],
        ["name" => "bag", "quantity" => 150, "color" => "blue"],
        ["name" => "box", "quantity" => 1200, "color" => "pink"],
        ["name" => "notebook", "quantity" => 50, "color" => "blue"],
        ["name" => "package", "quantity" => 1500, "color" => "green"],
        ["name" => "bag", "quantity" => 500, "color" => "green"],
        ["name" => "notebook", "quantity" => 100, "color" => "yellow"],
    ];

$tmp = array_column($objectListData4, 'name');
array_multisort($tmp, SORT_ASC, $objectListData4);

var_dump($objectListData4); // note the name 'notebook' and the order of the 'quantity' column.  the 'quantity' column has also been sorted but shouldnt be

转储数据:

array(10) { [0]=> array(3) { ["name"]=> string(3) "bag" ["quantity"]=> int(150) ["color"]=> string(4) "blue" } [1]=> array(3) { ["name"]=> string(3) "bag" ["quantity"]=> int(500) ["color"]=> string(5) "green" } [2]=> array(3) { ["name"]=> string(3) "box" ["quantity"]=> int(1000) ["color"]=> string(3) "red" } [3]=> array(3) { ["name"]=> string(3) "box" ["quantity"]=> int(1200) ["color"]=> string(4) "pink" } [4]=> array(3) { ["name"]=> string(8) "notebook" ["quantity"]=> int(50) ["color"]=> string(4) "blue" } [5]=> array(3) { ["name"]=> string(8) "notebook" ["quantity"]=> int(100) ["color"]=> string(6) "yellow" } [6]=> array(3) { ["name"]=> string(8) "notebook" ["quantity"]=> int(250) ["color"]=> string(6) "orange" } [7]=> array(3) { ["name"]=> string(7) "package" ["quantity"]=> int(1000) ["color"]=> string(5) "brown" } [8]=> array(3) { ["name"]=> string(7) "package" ["quantity"]=> int(1500) ["color"]=> string(5) "green" } [9]=> array(3) { ["name"]=> string(6) "pencil" ["quantity"]=> int(100) ["color"]=> string(6) "yellow" } }

谁能明白为什么第二个测试在不应该的时候也对数量进行排序??

【问题讨论】:

  • 这是记录在案的行为。在手册中,对于第一个示例,它声明 “第二个数组中对应于第一个数组(100 和 100)中相同条目的条目也已排序”。在您的情况下,这将是第二个数组 $objectListData4 中的条目对应于第一个数组 $tmp 中相同的 "notebook" 值。
  • 第一个数组中没有“100”。第一个数组仅包含键和名称,仅此而已 - 没有数量。
  • 引用是指示例数组,其中第一个数组的值为“100”。在您的情况下,这相当于第一个数组具有多个“笔记本”值,然后第二个数组按数量排序。 @GeorgeAppleton 的回答是正确的,你应该接受它。

标签: php sorting


【解决方案1】:

我不确定您的错误的原因是什么,我怀疑 array_multisort 通过查找下一个可用的关联键或其他东西对数组数组进行排序是未记录的功能。

但确保不会进行进一步排序的解决方案是将数组键作为第二个排序参数传入。您的第二个给定示例的工作版本:

$objectListData4 =  [
        ["name" => "package", "quantity" => 1000, "color" => "brown"],
        ["name" => "box", "quantity" => 1000, "color" => "red"],
        ["name" => "notebook", "quantity" => 250, "color" => "orange"],
        ["name" => "pencil", "quantity" => 100, "color" => "yellow"],
        ["name" => "bag", "quantity" => 150, "color" => "blue"],
        ["name" => "box", "quantity" => 1200, "color" => "pink"],
        ["name" => "notebook", "quantity" => 50, "color" => "blue"],
        ["name" => "package", "quantity" => 1500, "color" => "green"],
        ["name" => "bag", "quantity" => 500, "color" => "green"],
        ["name" => "notebook", "quantity" => 100, "color" => "yellow"],
    ];

$tmp = array_column($objectListData4, 'name');
array_multisort($tmp, SORT_ASC, array_keys($objectListData4), $objectListData4);

var_dump($objectListData4); // note the name 'notebook' and the order of the 'quantity' column.  the 'quantity' column has also been sorted but shouldnt be

它的输出:

array(10) {
  [0]=>
  array(3) {
    ["name"]=>
    string(3) "bag"
    ["quantity"]=>
    int(150)
    ["color"]=>
    string(4) "blue"
  }
  [1]=>
  array(3) {
    ["name"]=>
    string(3) "bag"
    ["quantity"]=>
    int(500)
    ["color"]=>
    string(5) "green"
  }
  [2]=>
  array(3) {
    ["name"]=>
    string(3) "box"
    ["quantity"]=>
    int(1000)
    ["color"]=>
    string(3) "red"
  }
  [3]=>
  array(3) {
    ["name"]=>
    string(3) "box"
    ["quantity"]=>
    int(1200)
    ["color"]=>
    string(4) "pink"
  }
  [4]=>
  array(3) {
    ["name"]=>
    string(8) "notebook"
    ["quantity"]=>
    int(250)
    ["color"]=>
    string(6) "orange"
  }
  [5]=>
  array(3) {
    ["name"]=>
    string(8) "notebook"
    ["quantity"]=>
    int(50)
    ["color"]=>
    string(4) "blue"
  }
  [6]=>
  array(3) {
    ["name"]=>
    string(8) "notebook"
    ["quantity"]=>
    int(100)
    ["color"]=>
    string(6) "yellow"
  }
  [7]=>
  array(3) {
    ["name"]=>
    string(7) "package"
    ["quantity"]=>
    int(1000)
    ["color"]=>
    string(5) "brown"
  }
  [8]=>
  array(3) {
    ["name"]=>
    string(7) "package"
    ["quantity"]=>
    int(1500)
    ["color"]=>
    string(5) "green"
  }
  [9]=>
  array(3) {
    ["name"]=>
    string(6) "pencil"
    ["quantity"]=>
    int(100)
    ["color"]=>
    string(6) "yellow"
  }
}

【讨论】:

  • 这确实在这种特定情况下修复了它。尽管不知道是什么导致它对一个数据集而不是另一个数据集进行未经请求的二次排序,这让我想知道这个修复是否在每种情况下都能修复它,或者它是否仍然看起来是随机的。并且不知道是什么导致了原始问题,这让我想知道这是否只是一个问题,有时当只有一列被排序时,或者它是否可能发生在超过 1 列时。需要深入研究 php 的内部结构来找出来。
  • 无论如何都会修复它,我添加的代码有效地禁用了进一步的二次排序。只需将您的排序数组放在前面,然后将要排序的数组放在后面
【解决方案2】:

也许this question 可以帮助你,另一方面,也许 usort() 是一个选择

usort($objectListData4, 'cmp');

function cmp($a, $b) {
    return strcmp($a['name'], $b['name']);
}

【讨论】:

    【解决方案3】:

    简短的回答:你不能使用 array_multisort() 来实现你想要的,因为如果两个成员比较相等,它们在排序数组中的相对顺序是未定义的。 (见http://php.net/manual/en/function.array-multisort.php中的注释)

    这意味着您不能期望您的“笔记本”保持其原始顺序。如果他们碰巧这样做了,那只是巧合。

    这里有一个解决方案。

    function jnlsort($a, $b)//if the names are same, sort by index. Otherwise, sort by name.
    {
        if (($a['name'] == $b['name']))
        {
            return strcmp($a['index'], $b['index']);
        }
    
        return strcmp($a['name'], $b['name']);
    }
    
    foreach($objectListData4 as $index => $obj)//add the index fields to preserve the order
    {
        $objectListData4[$index]["index"] = $index;
    }
    
    usort($objectListData4, 'jnlsort');
    
    foreach($objectListData4 as $index => $obj)//remove the index fields
    {
        unset($objectListData4[$index]["index"]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多