我有以下数组
$records = array(
array("postId"=>"1","grid"=>"6"),
array("postId"=>"2","grid"=>"3"),
array("postId"=>"3","grid"=>"6"),
array("postId"=>"4","grid"=>"3"),
array("postId"=>"5","grid"=>"3"),
array("postId"=>"6","grid"=>"12"),
array("postId"=>"7","grid"=>"3"),
);
我想对这个数组进行排序,使得任意数量的背靠背“网格”的总和等于12。
示例:上面数组中“网格”的值为:6,3,6,3,3,12,3
(6 + 6 = 12),(3 + 3 + 3 + 3 = 12),(12 = 12)因此新订单应为6,6,3,3,3,3,12
或3,3,3,3,12,6,6
或{{1} }
因此,在对数组进行排序后,新数组应如下所示:
6,3,3,6,3,3,12
我在php手册中搜索并找到了这些函数:sort,uasort,uksort,usort但我无法弄清楚如何使用它们。
您能告诉我如何使用PHP实现这一目标吗?
网格的值总是3或6或12(仅这三个数字)
$records=array(
array("postId"=>"1","grid"=>"6"),
array("postId"=>"3","grid"=>"6"),
array("postId"=>"2","grid"=>"3"),
array("postId"=>"4","grid"=>"3"),
array("postId"=>"5","grid"=>"3"),
array("postId"=>"7","grid"=>"3"),
array("postId"=>"6","grid"=>"12"),
);
答案 0 :(得分:4)
所以你不是真正的排序,而是重新排序以创建序列。我想你正在尝试做一些固定高度的砖块布局,你需要重新排序以填充每一行,并将其余部分留在最后。使用12,6,3
的给定固定变体,可以通过按降序对其进行排序 - 奇数个六,它将填充较小的三个。然而,这样的顺序将产生无聊的布局 - 让它更有趣你只需要重新排序一些帖子。为此,您需要创建临时容器并在其网格总和等于12时合并它。如果您留下一些临时容器,请将它们合并为一个并在与先前分组合并之前按降序排序。
说明我的概念的代码:
//auxiliary function to calculate sum of grids in given temporary container
function reduc($a) {
return array_reduce($a, function ($result, $item) {
return $result . $item['grid'] . ',';
}, '');
}
function regroup($records, $group_sum = 12) {
$temp = array();
$grouped = array();
foreach ($records as $r) {
if ($r['grid'] == $group_sum) {
$grouped[] = $r;
} else {
if (!$temp) {
$temp[] = array($r);
} else {
$was_grouped = false;
foreach ($temp as $idx => $container) {
$current_sum = sum_collection($container);
if ($current_sum + $r['grid'] <= $group_sum) {
$temp[$idx][] = $r;
if ($current_sum + $r['grid'] == $group_sum) {
$grouped = array_merge($grouped, $temp[$idx]);
unset($temp[$idx]);
}
$was_grouped = true;
break;
}
}
if (!$was_grouped) {
$temp[] = array($r);
}
}
}
}
if ($temp) {
//Sort descending, so biggest ones will be filled first with smalller
$rest = call_user_func_array('array_merge', $temp);
usort($rest, function($a, $b) {
return $b['grid'] - $a['grid'];
});
$grouped = array_merge($grouped, $rest);
}
return $grouped;
}
答案 1 :(得分:2)
问题是:
我想以一种任意数量的总和来对这个数组进行排序 支持“网格”等于12。
您可以尝试此操作(使用usort)
$records = array(
array("postId"=>"1","grid"=>"6"),
array("postId"=>"2","grid"=>"3"),
array("postId"=>"3","grid"=>"6"),
array("postId"=>"4","grid"=>"3"),
array("postId"=>"5","grid"=>"3"),
array("postId"=>"6","grid"=>"12"),
array("postId"=>"7","grid"=>"3"),
);
您的号码为3
4次,nimber 6
次为2次,号码为12
次。
// Sort (ASC)
usort($records, function($a, $b) {
return $a['grid'] - $b['grid'];
});
DEMO-1 (ASC)(3+3+3+3=12
,6+6=12
,12=12
)。
// Sort (DESC)
usort($records, function($a, $b) {
return $b['grid'] - $a['grid'];
});
DEMO-2 (DESC)(12=12
,6+6=12
,3+3+3+3=12
)。
使用(ASC)排序后的输出:
数组(
[0] => Array ( [postId] => 7 [grid] => 3 ) [1] => Array ( [postId] => 5 [grid] => 3 ) [2] => Array ( [postId] => 4 [grid] => 3 ) [3] => Array ( [postId] => 2 [grid] => 3 ) [4] => Array ( [postId] => 3 [grid] => 6 ) [5] => Array ( [postId] => 1 [grid] => 6 ) [6] => Array ( [postId] => 6 [grid] => 12 )
)
答案 2 :(得分:1)
此解决方案首先按网格大小降序进行排序,然后通过测试每个剩余元素与目前为止每行的总和来强制它下降:
$sum=0;
$grouped=array();
usort($records, function($a, $b) { return $a['grid']<$b['grid']; });
while ($records)
{
$next=reset($records);
if ($sum) foreach ($records as $next) if ($sum+$next['grid']<=12) break;
$grouped[]=$next;
$sum+=$next['grid'];
unset($records[array_search($next, $records)]);
if ($sum>=12) $sum=0;
}
<强>更新强>
结果表明,按降序排序足以解决仅使用3,6和12个元素的要求。一个12以及一个6然后单独一个6站,所有其他组合填充剩余的三分。 (出于某种原因,我认为算法也必须能够处理9个。)所以这就是你所需要的:
usort($records, function($a, $b) { return $a['grid']<$b['grid']; });
当然,这使得一个非常无聊的网格。
答案 3 :(得分:0)
在PHP&gt; = 5.3.0中,您可以使用usort()
和闭包(或全局变量作为黑客)来执行此操作。鉴于$records
:
$running_length = 0;
usort( $records, function( $a, $b ) use( $running_length ) {
$running_length += $a["grid"];
if( $running_length >= 12 ) return( true );
return( false );
});
如果将“网格”参数可视化为字符串长度,则最终结果$records
将按以下顺序排序:
... 3
... 3
...... 6
... 3
...... 6
... 3
............ 12
考虑到可用块的随机性,您可能希望首先从最小到最大排序此数组,然后查看它是否更适合您。这种方法显然不会检测到不适合的碎片和块 - 或者无法解析以适应。