Начинающий программист.
Я нахожусь в php, работая с ноделистом dom dom, состоящим из выбранных узлов, полученных из запроса XPath в XML файле. Выдержка содержания нодлиста:
<properties>
<property>
<price>270</price>
<address>3/2 Farran Street, Castlemaine, VIC, Australia</address>
<infants>3</infants>
</property>
<property>
<price>250</price>
<address>2/37 William Street, Castlemaine, VIC, Australia</address>
<infants>2</infants>
</property>
<property>
<price>250</price>
<address>2/37 William Street, Castlemaine, VIC, Australia</address>
<infants>3</infants>
</property>
...
Я хочу, чтобы отсортировать нодлист по price
по возрастанию, а в случае одинаковых цен, ни в из infants
нисходящих. В приведенном выше фрагменте, например, результатом будет:
<property>
<price>250</price>
<address>2/37 William Street, Castlemaine, VIC, Australia</address>
<infants>3</infants>
</property>
<property>
<price>250</price>
<address>2/37 William Street, Castlemaine, VIC, Australia</address>
<infants>2</infants>
</property>
<property>
<price>270</price>
<address>3/2 Farran Street, Castlemaine, VIC, Australia</address>
<infants>3</infants>
</property>
Я видел некоторые вопросы по сортировке, связанные с многомерными массивами, но я не могу перевести их в нодлисты. Я могу сортировать по price
ok (см. Ниже), но я не могу определить, как потом сортировать infants
.
$properties = iterator_to_array($matches); // where matches = a return from an XPath query
usort($properties, 'sortByPrice');
function sortByPrice ($a, $b) {
$aPrice = $a->getElementsByTagName("price");
$aPrice = $aPrice->item(0)->nodeValue;
$bPrice = $b->getElementsByTagName("price");
$bPrice = $bPrice->item(0)->nodeValue;
return (int) $aPrice - (int) $bPrice;
}
если ваш код работает нормально по цене, почему бы просто не расширить его:
$properties = iterator_to_array($matches); // where matches = a return from an XPath query
usort($properties, 'sortByPrice');
function sortByPrice ($a, $b) {
$aPrice = $a->getElementsByTagName("price");
$aPrice = $aPrice->item(0)->nodeValue;
$bPrice = $b->getElementsByTagName("price");
$bPrice = $bPrice->item(0)->nodeValue;
$r = (int) $aPrice - (int) $bPrice;
if (!$r) {
$ainfants = $a->getElementsByTagName("infants");
$ainfants = $ainfants->item(0)->nodeValue;
$binfants = $b->getElementsByTagName("infants");
$binfants = $bPrice->item(0)->nodeValue;
$r = (int) $ainfants - (int) $binfants;
}
return $r;
}
Вы можете получать скалярные значения в зависимости от узла контекста с DOMXPath::evaluate()
. number()
будет переводить первый узел в результат пути местоположения в поплавок. Если ни один узел не был найден, результат равен нулю.
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$properties = iterator_to_array($xpath->evaluate('//properties/property'));
usort(
$properties,
function(DOMElement $a, DOMElement $b) use ($xpath) {
$aPrice = (int)$xpath->evaluate('number(price)', $a);
$bPrice = (int)$xpath->evaluate('number(price)', $b);
if ($aPrice == $bPrice) {
$aInfants = (int)$xpath->evaluate('number(infants)', $a);
$bInfants = (int)$xpath->evaluate('number(infants)', $b);
return $bInfants - $aInfants;
}
return $aPrice - $bPrice;
}
);
Попробуйте эту функцию. Он действует как обобщение uasort
PHP uasort
:
function sortByKeyValue($the_array, $key)
{
$cmp_val="((\$a['$key']>\$b['$key'])?1:
((\$a['$key']==\$b['$key'])?0:-1))";
$cmp=create_function('$a, $b', "return $cmp_val;");
uasort($the_array, $cmp);
return $the_array;
}
В вашем случае вы можете использовать его таким образом:
$properties = iterator_to_array($matches);
sortByKeyValue($properties, 'price');
sortByKeyValue($properties, 'infants');
Я надеюсь, что это помогает.
eval()
. Медленно и опасно.