创建一个数组排序函数,确保相似的值不会相邻

时间:2016-07-20 19:25:09

标签: php arrays sorting

我有一个具有type属性的对象数组;有5种可能的'类型'。重要的是,元素被插入到数组中,并且应尽可能保留随机性;它只是第三方软件限制,迫使这种非邻接业务。

我想对该数组进行排序,以便没有相邻的值相同,或者,如果事实证明这是不可能的,则确保不可移动的对到达底部。

我试过这个:

function check_adjacency($obj_1, $obj_2) {
    return $obj_1->type == $obj_2->type ? 0 : 1;  // also tried -1
}
usort($arr, "check_adjacency");

我可以理解为什么这不起作用;没有返回1 vs -1的标准。但我对如何(有效地)在PHP中编写它感到困惑。我也尝试编写自己的函数来实现这一点,但我总是过早完成或无限循环。战略建议和解决方案都欢迎。

更新

请求示例:

为方便起见,我使用了顺序变量名,但实际上这些对象是以type属性的随机顺序添加到数组中的。

$objs = [ $obj_1, $obj_2, $obj_3, $obj_$4... $obj_300];
foreach($objs as $o) print $o->type

收率:

>> "t2", "t1", "t1", "t2", "t2", "t4", "t3", "t3", "t3", "t5", "t1", "t2"...

理想情况下,排序后会得到类似的东西。

>> "t2", "t1", "t2", "t4", "t3", "t1", "t3", "t2", "t3", "t5", "t1", "t2"

基本上,如果集合中的下一个元素具有与前一个元素相同的type属性,则将其删除并在此后的最早索引处插入。如果这还没有澄清,请告诉我。

编辑第二个:

想到一个更简单的解释方法。我有很多书 - 小书,中型书和大书。都有不同的头衔;我想要一个书架,上面没有两本相同大小的书籍,而这些书籍则是随机分布的。

1 个答案:

答案 0 :(得分:1)

分两步完成。首先创建一个二维数组,其键是type属性,元素是具有该类型的所有项的数组。然后遍历这些键,从每个组中删除一个项目并将其添加到结果数组中。

// step 1
$arr_by_type = array();
foreach ($arr as $el) {
    if (isset($arr_by_type[$el->type])) {
        $arr_by_type[$el->type][] = $el;
    } else {
        $arr_by_type[$el->type] = array($el);
    }
}

// step 2
$result = array();
while (!empty($arr_by_type)) {
    foreach ($arr_by_type as $type => &$sub_array) {
        $result[] = array_pop($sub_array);
        if (empty($sub_array)) {
            unset($result[$type]);
        }
    }
}
print_r($result);