Сортировка массива объектов SimpleXML

Я считал то, что я нашел на 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 ); 

Я видел, что люди говорят

"Используйте usort"

Сопровождаемый основным примером из руководства PHP, но это действительно не объясняет это. По крайней мере, не мне. Я также видел, что люди предлагают пользоваться внешней библиотекой как SimpleDOM, но я хочу избегать использования чего-то внешнего для этого (по-видимому, хотя я еще не могу решить его), мало вещи.

Любая справка ценится, Спасибо!

7
задан rg88 22 January 2010 в 18:57
поделиться

4 ответа

Я предполагаю, что люди предлагают использовать SimpleDom . :)

Я написал SIMPLEDOM :: Сортировать () именно для этой ситуации, потому что для того, чтобы сортировать симплексМлементов арбитражным выражением (или произвольными выражениями), необходимо использовать Array_Multisort () , который скучно и не научит тебе что-нибудь полезное.

Вот короткая версия того, как она работает: сначала вы создаете прокси-массив ключа => Пары значения, соответствующие каждому SimplexMlElement, и значение, с которым они будут отсортированы. В вашем примере, если вы хотите отсортировать их по , массив будет массив (21, 56) . Затем вы звоните Array_Multisort () с помощью «массива прокси» в качестве первого аргумента, за которым следует любое количество модификаторов сортировки , таких как sort_desc или sort_numeric, то, наконец, массив, который вы хотите сортировать, который будет передано посредством ссылки.

Вы получите что-то подобное:

$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);

, но на самом деле, вместо того, чтобы обременять себя с большим количеством кода, вам придется поддерживать и, возможно, заканчивать перезапись Array_Multisort () в пользовательском пространстве, вы должны Используйте существующие решения. В таком алгоритме / рутине / рутине нет ничего интересного, ваше время лучше потрачено на то, что еще не существует.

3
ответ дан 6 December 2019 в 23:05
поделиться

Я был готов рекомендовать USORT () , пока я не понял, что вы уже избили меня к нему. Поскольку примеры кода не сделали много хорошего в прошлом, я постараюсь просто объяснить это на простом английском языках и, надеюсь, что вы получите вам указание в правильном направлении.

Используя USORT () , вы создаете свой собственный пользовательский «алгоритм». Функция () [) функция () вызывает вашу собственную функцию сравнения, чтобы определить, как каждый из ваших объектов относится друг к другу. При написании вашей функции сравнения вы пройдете в два объекта в рамках вашего массива. С этими двумя объектами вы возвращаете результат, который по существу рассказывает USORT () , является ли первый объект меньше , , равно , или , больше, чем Второй объект. Вы делаете это, возвращая -1, 0 или 1 (соответственно). Вот и все. Вам приходится беспокоиться о том, как только два объекта сравниваются друг с другом, а фактическая механика сортировки обрабатывается 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');

Это в значительной степени пример в руководстве PHP, но, надеюсь, это имеет смысл в контексте сейчас. Дайте мне знать, если я не буду четко на что-то.

2
ответ дан 6 December 2019 в 23:05
поделиться

Функция позволяет вам сказать PHP

Эй, вы! Сортировать этот массив, я даю вам эту функцию, которую я написал.

Это не имеет ничего особенного с помощью Simplexml. Это общая функция для сортировки встроенного PHP встроенного сбора данных массива.

Вам необходимо написать функцию, метод экземпляра или статический метод для сортировки массива. Второй аргумент для USORT принимает обратный вызов , который является псевдо-типом, который позволяет указывать, какие функции, метод экземпляра или статический метод.

Функция, которую вы пишете, примут два аргумента. Это будут два разных значения из вашего массива

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.

4
ответ дан 6 December 2019 в 23:05
поделиться

Вот еще один пример использования 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>';
1
ответ дан 6 December 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: