Вы можете использовать очередь с минимальной кучей или с минимальным приоритетом (которая в PHP немного отличается). Если в этой куче есть k элементов, поменяйте местами верхний элемент кучи, когда вы найдете запись с лучшим значением, чем этот наименьший показатель в куче. Затем вы получите топовые записи k с наименьшим количеством очков наверху. Таким образом, в качестве последнего шага вы должны извлечь записи из кучи и изменить их порядок.
Вот как это может выглядеть, используя SplPriorityQueue. Обратите внимание, что эта структура помещает максимальные значения приоритета наверх, поэтому мы должны предоставить ей отрицательные оценки, чтобы получить минимальные оценки наверху кучи / очереди:
function getTop($input, $k) {
$q = new SplPriorityQueue();
$q->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY);
foreach ($input as $entry) {
if ($q->count() < $k) {
$q->insert($entry, -$entry["score"]); // negate score to get lower scores first
} else if ($entry["score"] > -$q->top() ) { // better score than least in queue? Exchange
$q->extract();
$q->insert($entry, -$entry["score"]);
}
}
$q->setExtractFlags(SplPriorityQueue::EXTR_DATA);
return array_reverse(iterator_to_array($q));
}
Вот некоторые примеры входных данных и способ вызова вышеуказанной функции:
$input = [
["user" => "a", "score" => 17],
["user" => "b", "score" => 3],
["user" => "c", "score" => 10],
["user" => "d", "score" => 11],
["user" => "e", "score" => 5],
["user" => "f", "score" => 19],
["user" => "g", "score" => 7],
["user" => "h", "score" => 2],
["user" => "i", "score" => 18],
["user" => "j", "score" => 12],
["user" => "k", "score" => 10],
["user" => "l", "score" => 6],
["user" => "m", "score" => 9],
["user" => "n", "score" => 15],
];
$top = getTop($input, 5);
print_r($top);