3v4l.org

run code in 300+ PHP versions simultaneously
<?php $values = [ [ 'id' => '2', 'category_id' => 'A', ], [ 'id' => '30', 'category_id' => 'A', ], [ 'id' => '12', 'category_id' => 'B', ], [ 'id' => '8', 'category_id' => 'B', ], [ 'id' => '10', 'category_id' => 'C', ], [ 'id' => '329', 'category_id' => 'D', ], [ 'id' => '89', 'category_id' => 'E', ], [ 'id' => '79', 'category_id' => 'E', ], [ 'id' => '58', 'category_id' => 'A', ], [ 'id' => '219', 'category_id' => 'B', ], [ 'id' => '44', 'category_id' => 'B', ], [ 'id' => '3219', 'category_id' => 'B', ], [ 'id' => '231', 'category_id' => 'B', ], [ 'id' => '43210', 'category_id' => 'F', ] ]; // 一次元配列にする $categoryIds = array_column($values, 'category_id'); // 処理済みの category_id を格納する変数 $sorted = []; // 残っている category_id が一種類のみかどうかを判定する変数 $hasOneSubject = false; $sorting = function ($categoryIds) use (&$sorting, &$sorted, &$hasOneCategory) { // 重複を削除した category_id $uniqueCategory = array_unique($categoryIds); // 使用済みの category_id を格納しておく変数 $used = []; foreach ($categoryIds as $index => $id) { // 処理済みの配列から一番最後を取得 $lastKey = array_key_last($sorted); // 残りの category_id が一種類しかない場合を除き、直近の配列が同じ場合はskip。 if (isset($sorted[$lastKey]) && $sorted[$lastKey] === $id && !$hasOneCategory) { continue; } // category_id を全種類使い切った場合は使用済みをリセットする if (count($uniqueCategory) === count(array_unique($used))) { $used = []; } // 既に同一の category_id を処理済みの場合はskip if (in_array($id, $used)) { continue; } $sorted[$index] = $id; $used[] = $id; } // 残りの配列 $diff = array_diff_assoc($categoryIds, $sorted); // 残りの配列が一種類かどうか $hasOneCategory = count(array_unique($diff)) === 1; // 残っている配列がある場合は再帰処理を実施 if (count($diff) > 0) { return $sorting($diff); } return $sorted; }; $sortedValues = []; // 二次元配列次元配列として入れ直す foreach ($sorting($categoryIds) as $key => $value) { $sortedValues[$key] = $values[$key]; } var_dump($sortedValues);

preferences:
27.52 ms | 402 KiB | 5 Q