Как в цикле учитывать вопросы, на которых не было ответа?

Доброго времени суток!

Код:
$answer = [
    1 => [2,3,4,5,52],
    2 => [7,8,9,52],
    3 => [10,11,12,25],
  ];

  $bd = [
    [
      'id' => 2,
      'id_question' => 1,
      'correct_answer' => 1,
    ],
    [
      'id' => 3,
      'id_question' => 1,
      'correct_answer' => 1,
    ],
    [
      'id' => 4,
      'id_question' => 1,
      'correct_answer' => 1,
    ],
    [
      'id' => 5,
      'id_question' => 1,
      'correct_answer' => 1,
    ],
    
    
    [
      'id' => 7,
      'id_question' => 2,
      'correct_answer' => 1,
    ],
    [
      'id' => 8,
      'id_question' => 2,
      'correct_answer' => 1,
    ],
    [
      'id' => 9,
      'id_question' => 2,
      'correct_answer' => 1,
    ],
    
    
    [
      'id' => 10,
      'id_question' => 3,
      'correct_answer' => 1,
    ],
    [
      'id' => 11,
      'id_question' => 3,
      'correct_answer' => 1,
    ],
    [
      'id' => 12,
      'id_question' => 3,
      'correct_answer' => 1,
    ],
    
    [
      'id' => 13,
      'id_question' => 4,
      'correct_answer' => 1,
    ],
    [
      'id' => 14,
      'id_question' => 4,
      'correct_answer' => 1,
    ],
    [
      'id' => 15,
      'id_question' => 4,
      'correct_answer' => 1,
    ],
  ];


  $quests = [];
  foreach ($bd as $bd_element) {
    $quests[$bd_element['id_question']][] = $bd_element['id'];
  }
  

  $a = 0;
  foreach ($quests as $id_quest => $ans) {
    $is = true;
    echo '<br><br>Вопрос: №'.$id_quest.'<br>';

    foreach ($ans as $an) {
      if (array_search($an, $answer[$id_quest]) === false) $is = false;
      echo 'Правильные ответы: '.$an.'<br>';
    }
    
    foreach ($answer[$id_quest] as $answer_give) {
      if (array_search($answer_give, $ans) === false) $is = false;
      echo 'Дан ответ: '.$answer_give.'<br>';
    }

	if ($is) $a++;
  }

  echo '<br><br>Правильных ответов: '.$a.'<br>';


Идет обработка ответов на вопросы. В вопросе может быть несколько вариантов ответа.
Код должен:
- учитывать только правильные ответы
- если выбраны не все правильные ответы - ответ не засчитывать
- если выбраны правильные и неправильные ответы - ответ на засчитывать
- если ответа на вопрос не было - ответ не засчитывать.

В коде выше, работают все пункты, кроме учета вопросов, на которые не было ответов.
Т.е. в примере есть 4 вопрос, на который не было ответа, но цикл считает его как правильный.
Никак не могу найти, где это поправить.

Заранее спасибо!
  • Вопрос задан
  • 204 просмотра
Решения вопроса 1
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
$allAnswers = [
    1 => [2,3,4,5],      // верный, тк даны только верные ответы
    2 => [7,8,9,52],     // не верный, дан неверный 52
    3 => [10,11,12,25],  // не верный, дан неверный 25
    4 => [13],           // не верный, тк пропущены верные ответы 14 и 15
];
$dbAnswers = [
     // данные из БД
];

/** 
 *  Группирует любой массив  по любому полю $indexKey в качестве индекса, 
 *  и $columnKey в качестве группируемых значений
 */
function groupBy(array $input, string $indexKey, string $columnKey): array
{
    return array_reduce($input,  function($res, $data) use ($indexKey, $columnKey){
        if (!isset($data[$indexKey], $data[$columnKey])) {
             return $res;
        }
        
        $res[$data[$indexKey]][] = $data[$columnKey];
            
        return $res;
    }, []);
}

/** 
 *  Маппинг введенных ответов с верными ответами по каждому вопросу
 */
function computeAnswersResult(array $inputAnswers, array $questionsWithCorrectAnswers): array
{
    $correctAnswers = $questionsWithCorrectAnswers[$questIn] ?? [];

    $result = [];
    foreach($inputAnswers as $questIn => $answesrIn) {
        $errors = array_diff($answesrIn, $correctAnswers);
        $corrects = array_diff($answesrIn, $errors); // если бы не нужно было выводить, то код сильно бы сократился
        $correctDiff = array_diff($correctAnswers, $corrects);
    
        // Если нет лишних ответов и число  введенных верных ответов 
        // совпадает с числом верных в БД, то статус положительный
        $completed = \count($errors) === 0 && \count($correctDiff) === 0;
    
        $result[$questIn] = [
            'errors'    => $errors,
            'corrects'  => $corrects,
            'completed' => $completed,
        ];
    }
    
    return $result;
}

// Группируем верные ответы по каждому вопросу
$questionsWithCorrectAnswers = groupBy($dbAnswers, 'id_question', 'id');
// Маппим введенные ответы на правильные и получаем результат
$result = computeAnswersResult($allAnswers, $questionsWithCorrectAnswers);
// Посчитаем успешные
$completedCount = \count(
    array_filter($result, function($answer) {
        return $answer['completed'] ?? false;
    })
);

//  ОТОБРАЖЕНИЕ       
$html = '';
foreach ($result as $questId => $details) {
    $status = $details['completed'] ? 'верный' : 'не верный';
    
    $html .= 'Вопрос №:' . $questId . PHP_EOL;
    $html .= 'Правильные ответы: '  . implode(', ', $details['corrects']) . PHP_EOL;
    $html .= 'Результат вопроса: '  . $status . PHP_EOL;
    $html .= '-------------------'  .  PHP_EOL;
}
$html .= 'Всего верных: ' . $completedCount;

echo $html;
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
25 апр. 2024, в 19:42
49000 руб./за проект
25 апр. 2024, в 19:41
2000 руб./за проект
25 апр. 2024, в 19:22
18000 руб./за проект