【问题标题】:PHP sort array of objects by two propertiesPHP按两个属性对对象数组进行排序
【发布时间】:2019-01-12 05:52:51
【问题描述】:

我有一个数组

Array
(
[0] => stdClass Object
    (
        [tab_option_name_selector] => 2
        [fieldtype] => notes
        [order] => 12
    )

[1] => stdClass Object
    (
        [tab_option_name_selector] => 2
        [fieldtype] => notes
        [order] => 8
    )

[2] => stdClass Object
    (
        [tab_option_name_selector] => 1
        [order] => 2
        [fieldtype] => selectbox
    )

[3] => stdClass Object
    (
        [tab_option_name_selector] => 2
        [order] => 3
        [fieldtype] => selectbox
    )
)

我正在尝试让这个 usort 函数工作

function osort(&$array, $props) 
{ 
    if(!is_array($props)) 
        $props = array($props => true); 

    $me = usort($array, function($a, $b) use ($props) { 
        foreach($props as $prop => $ascending) 
        { 
            if($a->$prop != $b->$prop) 
            { 
                if($ascending) 
                    return $a->$prop > $b->$prop ? 1 : -1; 
                else 
                    return $b->$prop > $a->$prop ? 1 : -1; 
            } 
        } 
        return -1; //if all props equal        
    });    
    print_r($props);
    return ($me);
} 


$tab = osort($objectArray, "tab_option_name_selector", "order"); 

所以按标签排序然后排序。

$tab 是空的 - 知道我做错了什么吗?

【问题讨论】:

  • 为什么额外的间接层级让事情变得更加混乱?为什么不 $sorted = usort($objectArray, "sortObjects"); 使用 sortObjects 根据选项卡和顺序值返回 -1/0/1? (如果标签不同,返回它们的 cmp,如果它们相同,返回命令 cmp,完成了吗?)
  • 嗨 @Mike'Pomax'Kamermans 很抱歉,我不明白如何按照您的建议进行操作
  • 你在说什么,你的代码已经这样做了。您无需直接使用自定义比较函数在名为 osort, only have your function do the comparison, and then just call usort 的函数中进行排序。

标签: php sorting object


【解决方案1】:

为什么会有额外的间接层级并使事情变得更加混乱?为什么不直接使用sortObjects($a,$b) 函数对usort($objectArray, "sortObjects"); 进行排序,该函数执行任何比较器的功能:根据输入返回负数/0/正数?

如果标签不同,返回它们的比较,如果它们相同,返回顺序比较;完成。

$array = array(
    (object)array(
        'tab_option_name_selector' => 2,
        'fieldtype' => 'notes',
        'order' => 12
    ),
    (object)array(
        'tab_option_name_selector' => 2,
        'fieldtype' => 'notes',
        'order' => 8
    ),
    (object)array(
        'tab_option_name_selector' => 1,
        'order' => 2,
        'fieldtype' => 'selectbox'
    ),
    (object)array(
        'tab_option_name_selector' => 2,
        'order' => 3,
        'fieldtype' => 'selectbox'
    )
);

function compareTabAndOrder($a, $b) {
    // compare the tab option value
    $diff = $a->tab_option_name_selector - $b->tab_option_name_selector;
    // and return it. Unless it's zero, then compare order, instead.
    return ($diff !== 0) ? $diff : $a->order - $b->order;
}

usort($array, "compareTabAndOrder");
print_r($array);

【讨论】:

    【解决方案2】:

    为什么不使用array_multisorthttp://php.net/manual/de/function.array-multisort.php

    $data = //your array
    
    //Create independent arrays
    foreach ($data as $row) {
      foreach ($row as $key => $value){
        ${$key}[]  = $value; 
        //Creates $tab_option_name_selector, $fieldtype and $order array
        //in order to use them as independent arrays in array_multisort.
      }  
    }
    
    array_multisort($tab_option_name_selector, SORT_ASC, $order, SORT_ASC, $data);
    
    //$data sorted as expected.
    echo "<pre>";
    print_r($data);
    echo "</pre>";
    

    【讨论】:

    • 这对于带有两行比较器的 usort 已经可以做的事情来说似乎有点过分了?
    • 更新了array_multisort 调用 - 参数顺序有误。
    • 作为对比:那将是非常糟糕的编程。如果您依赖这么多属性进行比较,那么您的对象应该只是具有比较功能的真实分类对象,存储在理解插入和就地排序的适当数据结构中。
    • @Mike'Pomax'Kamermans 好吧,如果你有一个表格,你要显示它并允许“多排序”(第一个 id、第二个名字、第三个日期......等等on)“本机”比较功能对您根本没有帮助。 array_multisort 只需要再提供一个数组即可实现所需的结果。
    猜你喜欢
    • 1970-01-01
    • 2014-09-17
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    相关资源
    最近更新 更多