正如问题所示,我使用uksort()
从多维数组中获得所需的排序。
除了一个小缺陷外,一切都很好。我无法确切地传达问题所在,但它几乎就像natsort()
被应用到某个地方而我无法弄清楚。
这是我的uksort()回调:
uksort($LoanPrograms, function($a, $b){
$yearA = abs((int) filter_var($a, FILTER_SANITIZE_NUMBER_INT));
$yearB = abs((int) filter_var($b, FILTER_SANITIZE_NUMBER_INT));
return $yearB > $yearA ? 1 : -1;
});
我只是从字符串中提取数字(我已经三次检查)。数字看起来像这样:
$a - 30
$b - 5
$a - 20
$b - 10
$a - 30
$b - 15
$a - 7
$b - 10
但问题是,7
被视为大于10
,而5
被视为大于30
......等。
我无法弄清楚这里可能出现的问题。非常感谢任何想法。
修改
多维数组的快照:
Array
(
[Conventional 15yr Fixed] => Array
(
[0] => Array
(
[HumanName] => Conventional 15yr Fixed
[Rate] => 2.875
)
)
[Conventional 20yr Fixed] => Array
(
[0] => Array
(
[HumanName] => Conventional 20yr Fixed
)
)
[Conventional 7/1 Arm] => Array
(
[0] => Array
(
[HumanName] => Conventional 7/1 Arm
)
……
)
答案 0 :(得分:1)
您提供的结果有以下原因:
return $yearB > $yearA ? 1 : -1;
要升序排序,您应该切换两个变量。请参阅下一点的手册中的引用。
manual on uksort
说回调函数(我强调):
如果第一个参数被认为分别小于,等于或者,则比较函数必须返回小于,等于,或大于零的整数。大于第二个。
因此,最好只返回两个参数的数值差异。对于升序排序:
return $yearA - $yearB;
具有分隔数字组的字符串可以提供意外值:例如" 7/1"将被消毒至71岁。
要解决此问题,您可以使用strpbrk代替filter_var:
function firstUnsignedInt($s) {
return (int) strpbrk($s, "0123456789");
}
uksort($LoanPrograms, function($a, $b){
// sort descending on first number in each string:
return firstUnsignedInt($b) - firstUnsignedInt($a);
});
您可以在eval.in上看到此代码。
array_multisort函数允许对数组进行排序,方法是应用排序相同大小的另一个数组时发生的相同顺序更改。为此,我们可以使用带有提取的数值的数组:
function firstUnsignedInt($s) {
return (int) strpbrk($s, "0123456789");
}
// Extract the numbers from all keys into a new array:
$terms = array_map('firstUnsignedInt', array_keys($LoanPrograms));
// Sort the numbers and let the original array follow the reordering:
array_multisort($terms, SORT_DESC, $LoanPrograms);
您可以在eval.in上看到此代码。
这可以使调试更容易,因为您可以使用提取的数字随时可用的数组。
答案 1 :(得分:0)
我没有看到它做的那种排序,我认为它只是向后排序。至少在以下测试中。并不是说它符合"答案",而是更多的数据。
$LoanPrograms = array("2" => "test", "10" => "test", "11" => "test", "1" => "test", "Conventional 15yr Fixed" => "test", "Conventional 20yr Fixed" => "test", "Conventional 7/1 Arm" => "test");
uksort($LoanPrograms, function($a, $b){
$yearA = abs((int) filter_var($a, FILTER_SANITIZE_NUMBER_INT));
$yearB = abs((int) filter_var($b, FILTER_SANITIZE_NUMBER_INT));
echo $yearA . ' ? ' . $yearB . " = " . ($yearB > $yearA ? 1 : -1) . "<br />";
return ($yearB > $yearA ? 1 : -1);
});
print_r($LoanPrograms);
给出:
1 ? 10 = 1
1 ? 11 = 1
1 ? 2 = 1
1 ? 15 = 1
1 ? 20 = 1
71 ? 1 = -1
11 ? 10 = -1
20 ? 11 = -1
11 ? 71 = 1
11 ? 2 = -1
15 ? 11 = -1
10 ? 2 = -1
20 ? 15 = -1
71 ? 20 = -1
Array ( [Conventional 7/1 Arm] => test [Conventional 20yr Fixed] => test [Conventional 15yr Fixed] => test [11] => test [10] => test [2] => test [1] => test )