数据库中用一个值来保存多种情况

请先读这篇文章

我这里就不再赘述了

基础状态

array(
  '1' => '灯'
  '2' => '床',
  '4' => '桌',
  '8' => '椅子',
  '16' => '饮水机',
  ……
);

数据库数据

mysql> select * from status;
+----+--------+-------------------------+------------+------------+
| id | status | content                 | created_at | updated_at |
+----+--------+-------------------------+------------+------------+
|  1 |     13 | 1-4-8 灯-桌子-椅子      |          0 |          0 |
|  2 |      7 | 1-2-4 灯-床-椅子        |          0 |          0 |
|  3 |     24 | 8-16 椅子-饮水机        |          0 |          0 |
+----+--------+-------------------------+------------+------------+

问题一,我们如何知道一个数字n,是由哪些组合,组合而成的

这里只贴出反解算法,,当然,,这应该不是最优解决方案

$statusArray = [
    1 => 1,
    2 => 2,
    4 => 4,
    8 => 8
];

/**
 * 根据一个状态值反解出有的状态值
 *
 * @param array $statusArray
 * @param int   $number
 * @param int   $base
 *
 * @return array
 */
function decodeStatus (array $statusArray, int $number, int $base = 2)
{
    if ($number < 0) throw new \Mockery\Exception('被解必须大于0');
    if (!$statusArray) throw new \Mockery\Exception('基本数据为空');
    if ($base <= 0) throw new \Mockery\Exception('基数必须大于0');
    $maxCount = count($statusArray) - 1;
    $list = [];
    for ($i = $maxCount; $i >= 0; $i--) {
        $index = pow($base, $i);
        $temp = $number - $index;
        if ($temp >= 0) {
            $list[] = $index;
            $number = $temp;
        }
    }

    return $list;
}

问题二,如果我们要检索状态中包含某一状态的数据,或者包含某几个状态的数据

$nums = [1,2];

$statusArray = [
    1 => 1,
    2 => 2,
    4 => 4,
    8 => 8
];

$header = [];
$footer = [];
foreach ($statusArray as $item) {
    if (in_array($item, $nums)) {
        $header[] = $item;
    } else {
        $footer[] = $item;
    }
}
$combination = [array_sum($nums)];
$step = 0;
while (count($footer) > 1){
    if ($step > 0) {
        $head = array_shift($footer);
        $header[] = $head;
    }
    $count = count($footer);
    for ($i = 0; $i < $count; $i++) {
        $combination[] = array_sum($header) + $footer[$i];
    }
    ++$step;
}