user3467855 user3467855 - 15 days ago 5
PHP Question

Dinamically detect number of options from string

I am trying to detect dynamically via regex the options from a question with different number of options. Questions could have options untill b, c, e or f, g.... current example is until d.

1. Which two OSI model layers have the same functionality as two layers of the TCP/IP model? (Choose two.)
a. data link
a. network*
a. physical
a. session


PHP - What I tried. This detects only for 4 options, if I add a 5th one or 6th one, or if I remove one it won't work.

$textarea = preg_match_all('#\d+\.\s(.*)\s*[a-zA-Z]\.\s(.*?)\s*(.*)\s*[a-zA-Z]\.\s(.*?)\s*(.*)\s*[a-zA-Z]\.\s(.*?)\s*(.*)\s*[a-zA-Z]\.\s(.*?)\s*(.*)\s*#i', $textarea, $matches);

Array
(
[0] => Array
(
[0] => 1. Which two OSI model layers have the same functionality as two layers of the TCP/IP model? (Choose two.)
a. data link
a. network*
a. physical
a. session
)

[1] => Array
(
[0] => Which two OSI model layers have the same functionality as two layers of the TCP/IP model? (Choose two.)
)

[2] => Array
(
[0] =>
)

[3] => Array
(
[0] => data link
)

[4] => Array
(
[0] =>
)

[5] => Array
(
[0] => network*
)

[6] => Array
(
[0] =>
)

[7] => Array
(
[0] => physical
)

[8] => Array
(
[0] =>
)

[9] => Array
(
[0] => session
)

)


REGEX ONLINE

http://regexr.com/3en2b

Answer

An example with a generator function:

Lets say you have this string:

$txt = <<<'EOD'
1. What is your name?
a. Theresa
b. Mike
c. Jugurtha
d. I don't know

2. What is your favorite animal?
a. Rabbit
b. Dog
c. Cat
d. Poney
e. Unicorn
EOD;

The generator function:

function getQuestionAnswers($fh) {
    while (false !== $line = fgets($fh)) {
        if (preg_match('~^(?:(?<Qno>[0-9]+)|(?<Ano>[a-z]+))\. (?<content>.*)~', $line, $m)) {
            if ($m['Ano']) {
                $result['answers'][] = ['no' => $m['Ano'], 'content' => $m['content']];
            } else {
                if (isset($result))
                    yield $result;

                $result = [
                    'question' => [
                        'no' => $m['Qno'],
                        'content' => $m['content']
                    ]
                ];
            }
        }
    }
    if (isset($result))
        yield $result;
}

How to use it:

$fh = fopen('data:text/plain;base64,' . base64_encode($txt), 'rb');

foreach (getQuestionAnswers($fh) as $qas) {
    printf("Question number %d with %d answers\n", $qas['question']['no'], count($qas['answers']));
}

fclose($fh);
Comments