我如何按嵌套的php数组排序

时间:2020-12-15 15:55:37

This is an excerpt from the xml feed I'm accessing:

这是我正在访问的xml提要的摘录:

我如何按嵌套的php数组排序

And here's my current code:

这是我目前的代码:

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

This is the output: 我如何按嵌套的php数组排序

这是输出:

My question is, how do I get the table to sort in descending numerical order (i.e. most recent year first)? I've searched here and tried to understand the sort() function (e.g. this answer), but it's a bit beyond me still and I can't figure out how to get that to work here.

我的问题是,如何让表格以递减的数字顺序排序(即最近一年的第一年)?我在这里搜索并尝试理解sort()函数(例如这个答案),但它仍然有点超出我的范围,我无法弄清楚如何在这里工作。


UPDATE

I'm playing around with @Chris Goddard's answer below..

我正在玩@Chris Goddard的答案。

This is the code I've got, but it doesn't seem to have done the trick:

这是我得到的代码,但它似乎没有做到这一点:

<?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)."</pre>";
?>

What am I doing wrong?

我究竟做错了什么?

3 个解决方案

#1


1  

I dont understand half of that code (what's all the regex for?), but to achieve desired sorted table you can simply do:

我不明白一半的代码(什么是正则表达式?),但要实现所需的排序表,你可以简单地做:

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

to load the XML and get the list of all productions as they appear in the XML. To sort them you can use a custom sort:

加载XML并获取XML中出现的所有产品的列表。要对它们进行排序,您可以使用自定义排序:

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

which will compare the startdates of the simplexml elements and sort them in descending order. And then it's only a matter of just iterating the productions:

它将比较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>

See demo

Also see this demo for your additional requests in chat, e.g. limit productions to those with a review and sorting works by production startdate.

另请参阅此演示,了解聊天中的其他请求,例如:将生产限制为那些通过生产startdate进行审查和分类的人。

#2


1  

array_multisort will do the trick

array_multisort会做的伎俩

you put an array in the first one (which has the keys of each element, and the sorting value, the direction then the big array)

你把一个数组放在第一个(具有每个元素的键,排序值,方向,然后是大数组)

Edit

$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) { ...

#3


1  

you can place the values in an array, then use usort to sort by a user defined function.

您可以将值放在数组中,然后使用usort按用户定义的函数进行排序。

And notice that the elements are cast to string when they are set in the array. Comparing them as the XML objects they are isn't what you want.

请注意,元素在数组中设置时会转换为字符串。将它们作为XML对象进行比较并不是您想要的。

A little explanation:

一点解释:

First I'm placing the XML data into an array, just because the data is easier to work with that way.

首先,我将XML数据放入数组中,因为数据更容易以这种方式工作。

Then, I sort the array based on my custom function date_sort. Looking at the documentation for usort you see:

然后,我根据自定义函数date_sort对数组进行排序。查看用于问题的文档,您会看到:

The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

如果第一个参数被认为分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。

So, because you want to sort by date desc, if the dates are equal then the sort order is also equal(return 0), if the date is later it should be earlier in the list (return -1), and if the date is greater it should be later in the list (return 1)

因此,因为你想按日期desc排序,如果日期相等,那么排序顺序也是相等的(返回0),如果日期晚于它应该在列表中较早(返回-1),如果日期它应该在后面的列表中更大(返回1)

Then you just traverse through the array printing as you go.

然后,您只需遍历阵列打印即可。

If you want to use additional data, just place it in the array in the first loop.

如果要使用其他数据,只需将其放在第一个循环中的数组中即可。

$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


1  

I dont understand half of that code (what's all the regex for?), but to achieve desired sorted table you can simply do:

我不明白一半的代码(什么是正则表达式?),但要实现所需的排序表,你可以简单地做:

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

to load the XML and get the list of all productions as they appear in the XML. To sort them you can use a custom sort:

加载XML并获取XML中出现的所有产品的列表。要对它们进行排序,您可以使用自定义排序:

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

which will compare the startdates of the simplexml elements and sort them in descending order. And then it's only a matter of just iterating the productions:

它将比较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>

See demo

Also see this demo for your additional requests in chat, e.g. limit productions to those with a review and sorting works by production startdate.

另请参阅此演示,了解聊天中的其他请求,例如:将生产限制为那些通过生产startdate进行审查和分类的人。

#2


1  

array_multisort will do the trick

array_multisort会做的伎俩

you put an array in the first one (which has the keys of each element, and the sorting value, the direction then the big array)

你把一个数组放在第一个(具有每个元素的键,排序值,方向,然后是大数组)

Edit

$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) { ...

#3


1  

you can place the values in an array, then use usort to sort by a user defined function.

您可以将值放在数组中,然后使用usort按用户定义的函数进行排序。

And notice that the elements are cast to string when they are set in the array. Comparing them as the XML objects they are isn't what you want.

请注意,元素在数组中设置时会转换为字符串。将它们作为XML对象进行比较并不是您想要的。

A little explanation:

一点解释:

First I'm placing the XML data into an array, just because the data is easier to work with that way.

首先,我将XML数据放入数组中,因为数据更容易以这种方式工作。

Then, I sort the array based on my custom function date_sort. Looking at the documentation for usort you see:

然后,我根据自定义函数date_sort对数组进行排序。查看用于问题的文档,您会看到:

The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

如果第一个参数被认为分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。

So, because you want to sort by date desc, if the dates are equal then the sort order is also equal(return 0), if the date is later it should be earlier in the list (return -1), and if the date is greater it should be later in the list (return 1)

因此,因为你想按日期desc排序,如果日期相等,那么排序顺序也是相等的(返回0),如果日期晚于它应该在列表中较早(返回-1),如果日期它应该在后面的列表中更大(返回1)

Then you just traverse through the array printing as you go.

然后,您只需遍历阵列打印即可。

If you want to use additional data, just place it in the array in the first loop.

如果要使用其他数据,只需将其放在第一个循环中的数组中即可。

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