代码之家  ›  专栏  ›  技术社区  ›  rg88

对SimpleXML对象数组进行排序

  •  7
  • rg88  · 技术社区  · 15 年前

    我已经阅读了我在Stackoverflow上发现的内容,但对此仍不清楚。

    我有一个SimpleXML对象数组,如下所示:

    array(2) {
      [0]=>
      object(SimpleXMLElement)#2 (2) {
        ["name"]=>
        string(15) "Andrew"
        ["age"]=>
        string(2) "21"
      }
      [1]=>
      object(SimpleXMLElement)#3 (2) {
        ["name"]=>
        string(12) "Beth"
        ["age"]=>
        string(2) "56"
      }
    }
    

    我希望能够按任何列进行排序,升序或降序。比如:

    sort($data, 'name', 'asc');
    

    我可以传入上面的对象数组,并根据我喜欢的键的值进行排序。

    作为参考,类似的.NET解决方案将遵循以下思路:

    XmlSortOrder order = XmlSortOrder.Ascending;
        if ( sortDirection == "asc" ) {
            order = XmlSortOrder.Ascending;
        }
        expression.AddSort( columnSortingOn + "/text()", order, 
            XmlCaseOrder.UpperFirst, "en-us", XmlDataType.Text ); 
    

    我见过有人说

    感谢您的帮助,谢谢!

    6 回复  |  直到 15 年前
        1
  •  3
  •   Josh Davis    15 年前

    我猜人们建议使用 SimpleDOM 是我。:)

    array_multisort() 这很无聊,不会教你任何有用的东西。

    下面是其工作原理的简短版本:首先创建一个key=>的代理数组;对应于每个SimpleXMLElement的值对以及它们将被排序的值。在您的示例中,如果要按 <age/> ,数组将是 array(21, 56) 数组_multisort() 以“代理数组”作为第一个参数,后跟任意数量的 sorting modifiers

    $nodes = array(
        new SimpleXMLElement('<person><name>Andrew</name><age>21</age></person>'),
        new SimpleXMLElement('<person><name>Beth</name><age>56</age></person>')
    );
    
    function xsort(&$nodes, $child_name, $order = SORT_ASC)
    {
        $sort_proxy = array();
    
        foreach ($nodes as $k => $node)
        {
            $sort_proxy[$k] = (string) $node->$child_name;
        }
    
        array_multisort($sort_proxy, $order, $nodes);
    }
    
    xsort($nodes, 'name', SORT_ASC);
    print_r($nodes);
    
    xsort($nodes, 'age', SORT_DESC);
    print_r($nodes);
    

    但实际上,与其让自己承担更多的代码负担,还不如让自己维护并最终重写代码 在用户空间中,您应该利用现有的解决方案。这样的排序算法/例程没有什么有趣的,你最好把时间花在一些不存在的东西上。

        2
  •  4
  •   Alana Storm    15 年前

    usort 函数允许您告诉PHP

    嘿,你!使用我编写的函数对数组进行排序。

    您需要编写函数、实例方法或静态方法来对数组进行排序。usort的第二个参数接受 PHP Callback ,这是一种伪类型,用于指定函数、实例方法或静态方法。

    function cmp($a, $b)
    {
                if ($a == $b) {
                    return 0;
                }
                if($a < $b) {
                    return -1;
                }
                if($a > $b) {
                    return 1;
                }
    }
    

    您需要编写此函数以返回三个值之一。

    If $a == $b, return 0
    If $a > $b, return -1
    if $a > $v, return 1  
    

    当您调用usort时,PHP将在数组中运行,调用排序函数/方法(在本例中) cmp 一遍又一遍,直到数组被排序。在您的示例中,$a和$b将是SimpleXML对象。

        3
  •  2
  •   Bret Kuhns    15 年前

    我准备向你推荐 usort()

    利用 ,您可以创建自己的用户生成的“算法”。这个 usort() 函数调用您自己的比较函数来确定每个对象之间的关系。编写比较函数时,将在数组中传递两个对象。对于这两个对象,您将返回一个结果,该结果本质上说明 usort() 第一个对象是否为 LESS THAN , EQUAL TO GREATER THAN usort()

    好,现在来看一个半实际的例子:

    function myCompare($obj1, $obj2) {
        if($obj1->someInt == $obj2->someInt) {
            return 0; // equal to
        } else if($obj1->someInt < $obj2->someInt) {
            return -1; // less than
        } else {
            return 1; // greater than
        }
    }
    
    $myArray = {a collection of your objects};
    
    usort($myArray, 'myCompare');
    

        4
  •  1
  •   GZipp    15 年前

    下面是另一个使用 usort()

    function sort_obj_arr(& $arr, $sort_field, $sort_direction)
    {
        $sort_func = function($obj_1, $obj_2) use ($sort_field, $sort_direction)
        {
            if ($sort_direction == SORT_ASC) {
                return strnatcasecmp($obj_1->$sort_field, $obj_2->$sort_field);
            } else {
                return strnatcasecmp($obj_2->$sort_field, $obj_1->$sort_field);
            }
        };
        usort($arr, $sort_func);
    }
    

    测试代码;

    class TestClass
    {
        public $name;
        public $age;
    
        public function __construct($name, $age)
        {
            $this->name = $name;
            $this->age  = $age;
        }
    }
    
    $test[] = new TestClass('Tom', 28);
    $test[] = new TestClass('Mary', 48);
    $test[] = new TestClass('Beth', 38);
    $test[] = new TestClass('Cindy', 18);
    $test[] = new TestClass('Sid', 58);
    $test[] = new TestClass('Mandy', 8);
    
    $field = 'age';
    $direction = SORT_DESC;
    sort_obj_arr($test, $field, $direction);
    
    echo '<pre>';
    print_r($test);
    echo '</pre>';
    
        5
  •  1
  •   user3116221    11 年前

    这是一个古老的线程,但这里是我的解决方案,用于从rss提要中提取信息,以便按标题排序

    $xml =  simplexml_load_file('rss.xml');
    $msg = array();
    $msg_count = $xml->channel->item->count();
    
    for ($x=0;$x<$msg_count;$x++){
        $msg[$x]['titl'] = (string)$xml->channel->item[$x]->title;
        $msg[$x]['link'] = (string)$xml->channel->item[$x]->link;
        $msg[$x]['date'] = (string)$xml->channel->item[$x]->pubDate;
        $msg[$x]['time'] = strtotime(substr((string)$xml->channel->item[$x]->pubDate,4));
        $msg[$x]['desc'] = (string)$xml->channel->item[$x]->description;
        $msg[$x]['auth'] = (string)$xml->channel->item[$x]->author;
    }
    
    foreach ($msg as $key => $row) {
        $titl[$key] = $row['titl'];
        $link[$key] = $row['link'];
        $pdat[$key] = $row['date'];
        $time[$key] = $row['time'];
        $cate[$key] = $row['cate'];
        $desc[$key] = $row['desc'];
        $auth[$key] = $row['auth'];
    }
    
    array_multisort(
    //change $titl to any variable created by "foreach"
        $titl, SORT_ASC,SORT_NATURAL | SORT_FLAG_CASE,
        $msg);