<?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:
26.42 ms | 409 KiB | 5 Q