使用 PHP 安插固定排序 & 隨機排序卡片

by Benmr

前言

在特定情境下,我們想要把 array 裡的東西同時照特定的方式做排序
其中有幾個是固定的,有幾個是隨機的
比如說我們有 itemA ~ itemF 總共六個 item
file

我們想要把排序第一、第三的給固定下來
同時讓排序第二、第四個從 itemA ~ itemF 給取出但不重複
file

所以結果可能是這樣
file

也可能是這樣
file

那要怎麼做呢?
以下就架構,分兩個部份討論

架構

一、存 db 格式

為簡化討論
我們假設 itemTable 裡只有三個欄位
分別是 id、name、sort

在存資料時
我們把要固定欄位的紀錄之 sort 設為正數
(下圖例為 1、3)
而隨機排序的資料 sort 設為 -1
file

這樣的好處是我們一眼就可以知道
哪些紀錄是要固定欄位、哪些又是要隨機排序的

二、排序方式

這邊先理理頭緒
用自然語言寫出接下來要怎麼處理排序
(大概就是 Pseudocode 的概念)
然後再來寫 code 會比較順

自然語言版

  1. 將隨機排序的 $aryWithoutOrder 資料過濾出來 (sort = -1 的資料)
  2. 新增一個新的 $newAry 並把要固定排序的資料放進去
  3. $newAry 裡面沒有資料的位置填滿,
    填滿的方式為從 $aryWithoutOrder 隨機取出

正式寫 code 版

public static function do_sortItems($items = [])
{
    // 假設有 5 個 item
    // 固定 itemA、itemC 為欄位 1 & 3 (sort 為 1 & 3)
    // 其他的隨機排序 (設為 -1)
    $items =
        [
            [
                'name' => 'itemA',
                'sort' => 1,
            ],
            [
                'name' => 'itemB',
                'sort' => -1,
            ],
            [
                'name' => 'itemC',
                'sort' => 3,
            ],
            [
                'name' => 'itemD',
                'sort' => -1,
            ],
            [
                'name' => 'itemE',
                'sort' => -1,
            ]
        ];

    // 先將隨機排序的 item 取出放到 $aryWithouOrder 裡
    $aryWithoutOrder = \__::filter($items, function($n) {
       return $n['sort'] < 0;
    });

    $newAry = [];

    // 最多取 8 個 item 出來
    $maxLength = safeCount($items) < 8 ? safeCount($items) : 8;

    // 使用 bottomline 裡的 filter function 來取出已固定 sort 的item
    // 並存到 $newAry 裡
    for ($i = 0; $i < $maxLength; $i++) {
        $newAry[$i] = \__::filter($items, function ($n) use ($i) {
           return $n['sort'] ==  $i + 1 ? $n['sort'] ==  $i + 1 : [];
        });
    }

    // 逐一檢查 $newAry ,若 value 為空,則隨機從 $aryWithoutOrder 裡拿一個 item 出來
    // 同時將該 item 從 $aryWithoutOrder 裡拿掉
    foreach ($newAry as $i => $j) {
        if (empty($j)) {
            $randomKey = rand(0, safeCount($aryWithoutOrder) -1);
            $newAry[$i] = $aryWithoutOrder[$randomKey];
            $newAry[$i]['sort'] = $i+1;
            $aryWithoutOrder = array_splice($aryWithoutOrder, $randomKey, 1);
        }
    }

    return $newAry;
}

參考資料:

You may also like

Leave a Comment