PHP Сортировка массива на основе списка значений - PullRequest
0 голосов
/ 12 апреля 2020

Я ищу подход для сортировки массива массивов.

Вот упрощенный пример;

$myArray = [ 
  ['ref' => 103, 'refList' => '101,102,111'],
  ['ref' => 104, 'refList' => '101,103'],
  ['ref' => 105, 'refList' => '106,103'],
  ['ref' => 106, 'refList' => '103,104,110'],
];

Правило сортировки для элементов массива:

Элементы со ссылками, содержащимися в 'refList', должны идти после любых элементов с совпадающим 'ref'

Так что в этом сценарии правильный порядок будет;

  ['ref' => 103, 'refList' => '101,102,111'],
  ['ref' => 104, 'refList' => '101,103'],
  ['ref' => 106, 'refList' => '103,104'],
  ['ref' => 105, 'refList' => '106,103,110'],

Я пробовал несколько очень многословных подходов, а также usort (), но не могу понять это правильно. Я пошел по следующему маршруту:

usort($myArray, 'refSorter');

function refSorter($a, $b) {

    $arrayOfRefs = explode(',', $b['refList']);

    if (in_array($a['ref'], $arrayOfRefs)) {
        return 1;
    }
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

Правило сортировки несколько двусмысленно, но как насчет этого (измените, чтобы он соответствовал точным критериям):

function refSorter($a, $b) {

    $arrayOfRefsa = explode(',', $a['refList']);
    $arrayOfRefsb = explode(',', $b['refList']);

    $refCmp =  $a['ref'] === $b['ref'] ? 0 : ($a['ref'] < $b['ref'] ? -1 : 1);
    $refListCmp = in_array($b['ref'], $arrayOfRefsa) ? 1 : (in_array($a['ref'], $arrayOfRefsb) ? -1 : 0);
    return $refListCmp*10+$refCmp;
}

Дает правильный вывод для примера, указанного списка (проверено)

0 голосов
/ 12 апреля 2020

В вашем алгоритме сравнения пропущен один случай. Вы должны вернуть -1, когда A ref включен в B refList и 1, если B ref включен в A refList.

$myArray = [ 
  ['ref' => 103, 'refList' => '101,102,111'],
  ['ref' => 104, 'refList' => '101,103'],
  ['ref' => 105, 'refList' => '106,103'],
  ['ref' => 106, 'refList' => '103,104,110'],
];

usort($myArray, 'refSorter');

function refSorter($a, $b) {
    $aRefs = explode(',', $a['refList']);
    $bRefs = explode(',', $b['refList']);

    if (in_array($a['ref'], $bRefs)) {
        return -1;
    }

    if (in_array($b['ref'], $aRefs)) {
        return 1;
    }

    return $a['ref'] <=> $b['ref'];
}

Результат:

ref => 103 | refList => 101,102,111
ref => 104 | refList => 101,103
ref => 106 | refList => 103,104,110
ref => 105 | refList => 106,103

PHPSandbox

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...