Группирование элементов по сходным значениям вряд ли можно назвать алгоритмом. Это скорее шаблон кодирования, если что-нибудь еще.
Хороший способ написания кода - отделить механизм от намерения. В этом случае механизм состоит в том, как отслеживать значения ключей, чтобы найти границы группировки, и цель состоит в том, чтобы вывести HTML для каждой последовательной группы.
Например, Python имеет библиотечную функцию groupby, которая делает именно это. Поэтому в Python код будет выглядеть примерно так (без учета того факта, что для этого будет использоваться библиотека шаблонов):
from itertools import groupby
def question_from_row(row):
return dict(id=row['question_id'], body=row['question_body'])
for question, choices in groupby(questions, key=question_from_row):
print('<div class="question" id="%s">' % question['id'])
print(' <p>%s</p>\n' % question['body'])
print(' <div class="choices">')
for choice in choices:
print('<span class="choice">%s</span>' % choice['choice_body'])
print(' </div>')
print('</div>')
Насколько мне известно, PHP не имеет ничего подобного, но наивная реализация довольно проста:
function array_groupby($input, $keyfunc) {
$output = array();
$last_key = null;
$current = null;
foreach ($input as $item) {
$item_key = $keyfunc($item);
if ($last_key === null || $item_key != $last_key) {
if ($current !== null) {
$output[] = $current;
}
$last_key = $item_key;
$current = array();
}
$current[] = $item;
}
if ($current !== null) {
$output[] = $current;
}
return $output;
}
Это будет типичный библиотечный код, который вы включаете. Код, который имеет дело с выводом, становится довольно тривиальным. Полностью изолирован от того, как происходит группировка. Например, вы можете изменить array_groupby, чтобы он возвращал объект, который реализует интерфейс Iterator и только лениво выбирает из входного итерируемого.
$questions = array_groupby(pg_fetch_array($choices),
function($choice) { return $choice['id']; });
foreach ($questions as $choices) {
$question = $choices[0];
echo '<div class="question" id="'.$question['id'].'">';
echo '<p>'.$question['body'].'</p>';
echo '<div class="choices">';
foreach ($choices as $choice) {
echo '<span class="choice">'.$choice['choice_body'].'</span>';
}
echo '</div>';
echo '</div>';
}
В этом примере используется функция замыканий в PHP 5.3. В более старых версиях указание функции для извлечения группирующего ключа было бы несколько уродливее, возможно, требуя объектно-ориентированного подхода.