Как отсортировать по вложенному массиву php - PullRequest
2 голосов
/ 14 октября 2011

Это выдержка из XML-канала, к которому я обращаюсь :

xml feed

А вот мой текущий код:

$file = file_get_contents('feed.xml');
$file = preg_replace('/(<role[^>]+>)([^<]+)/si', '$1', $file);
$xml = new SimpleXMLElement($file);

$search_term = preg_replace('/[,.\/\\\(\)\[\]\{\}`~!@#\$%\^&*;:\'"\-_<>]*/is', '', $_GET['work']);

$productions = $xml->xpath('//production');
?>

<table width="300px" cellspacing="5px" cellpadding="5px" border="1px" >
<tr>
<th>year</th>
<th>company</th>
</tr>

<?php
foreach($productions as $prod) {

    $prod_attrs = $prod->attributes();
    $prod_date = $prod_attrs->startdate;

    echo "<tr><td>", $prod_date, "</td><td>", html_encode($prod_attrs->company), "</td></tr>";


    }               
?>

</table>

Это вывод: table

Мой вопрос: как мне получить таблицу для сортировки в порядке убывания чисел (т. Е. Самый последний год сначала)?Я искал здесь и пытался понять функцию sort() (например, этот ответ ), но это все еще немного вне меня, и я не могу понять, как заставить это работать здесь.


ОБНОВЛЕНИЕ

Я играю с @ ответом Криса Годдарда ниже ..

Этоу меня есть код, но он, похоже, не сработал:

<code><?php


    function html_encode($var){

    $var = html_entity_decode($var, ENT_QUOTES, 'UTF-8');
    $var = htmlentities($var, ENT_QUOTES, 'UTF-8');
    return $var;
}


$file = file_get_contents('feed.xml');
$file = preg_replace('/(<role[^>]+>)([^<]+)/si', '$1', $file);
$xml = simplexml_load_string($file);
$json = json_encode($xml); 
$array = json_decode($json,TRUE); 


$search_term = preg_replace('/[,.\/\\\(\)\[\]\{\}`~!@#\$%\^&*;:\'"\-_<>]*/is', '', $_GET['work']);


$works = $xml->xpath('//work');

foreach($works as $work) {
$Productions = $work->xpath('./production');

$Sorter = array();

foreach ($Productions as $prod) {

$prod_attrs = $prod->attributes();
    $Sorter[$key] = $prod_attrs->startdate;
array_multisort($Sorter, SORT_DESC, $Productions);
  }
}
echo "<pre>".print_r($works, true)."
";?>> 1030 *

Что я делаю не так?

Ответы [ 3 ]

1 голос
/ 14 октября 2011

вы можете поместить значения в массив, а затем использовать usort для сортировки по определенной пользователем функции.

И обратите внимание, что элементы преобразуются в строку, когда они установлены в массиве. Сравнивать их как объекты XML они не то, что вы хотите.

Небольшое объяснение:

Сначала я помещаю данные XML в массив только потому, что с этими данными проще работать.

Затем я сортирую массив на основе моей пользовательской функции date_sort. Глядя на документацию по usort, вы видите:

Функция сравнения должна возвращать целое число меньше, равно или больше нуля, если первый аргумент считается соответственно меньше, равно или больше второго.

Итак, поскольку вы хотите отсортировать по дате desc, если даты равны, то порядок сортировки также равен (возврат 0), если дата более поздняя, ​​она должна быть раньше в списке (возврат -1), и если дата больше, она должна быть позже в списке (возврат 1)

Тогда вы просто проходите массивную печать по ходу.

Если вы хотите использовать дополнительные данные, просто поместите их в массив в первом цикле.

$production_array = array();
foreach($productions as $prod) {

    $prod_attrs = $prod->attributes();
    $prod_date = $prod_attrs->startdate;
    $production_array[] = array(
        'date'=>(string) $prod_date,
        'company'=>(string) $prod_attrs->company,
        'review_en'=>(string) $prod->review['quote'],
        'review_de'=>(string) $prod->review->translation
    );
}
usort($production_array, 'date_sort');

foreach($production_array as $production) {
    echo "<tr><td>", $production['date'], "</td><td>", html_encode($production['company']), "</td><td>",$production['review_en'], "</td></tr>";
}

function date_sort($a, $b) {
    if($a['date'] == $b['date']) return 0;
    return $a['date'] > $b['date'] ? -1 : 1;
}
1 голос
/ 19 октября 2011

Я не понимаю половину этого кода (для чего все эти регулярные выражения?), Но для достижения желаемой отсортированной таблицы вы можете просто сделать:

$profile = simplexml_load_file('http://andrewfinden.com/test/feed.xml');
$productions = $profile->xpath(
    '/profile/repertoire/composer/work/role/production'
);

, чтобы загрузить XML и получить список всех произведенийкак они появляются в XML.Чтобы отсортировать их, вы можете использовать пользовательскую сортировку:

usort($productions, function($a, $b) {
    return $b['startdate'] - $a['startdate'];
});

, которая будет сравнивать начальные даты элементов simplexml и сортировать их в порядке убывания.И тогда это всего лишь вопрос итерации производства:

<table>
    <thead>
        <tr>
            <th>Year</th>
            <th>Company</th>
        </tr>
    </thead>
    <tbody>
    <?php foreach ($productions as $production): ?>
        <tr>
            <td><?php echo htmlspecialchars($production['startdate'])?></td>
            <td><?php echo htmlspecialchars($production['company'])?></td>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>

См. Демонстрацию

Также см. Эту демонстрацию для дополнительных запросов в чат , например, ограничить производство работами с проверкой и сортировкой по дате запуска производства.

1 голос
/ 14 октября 2011

array_multisort выполнит трюк

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

Редактировать

$Productions = json_decode(json_encode((array) simplexml_load_string($file)), 1);
$Sorter = array();

foreach ($Productions as $Key => $prod)
    $Sorter[$Key] = $prod->attributes->startdate;
array_multisort($Sorter, SORT_DESC, $Productions);

foreach ($Productions as $prod) { ...
...