Question

I am using strpos() function to find the string in an array key members.

    foreach($_POST as $k => $v){
    // for all types of questions of chapter 1 only
    $count = 0;
    if(strpos($k, 'chap1') !== false){
        $count++;
    }
}

I know that it works only until the keys are (chap1e1, chap1m1, chap1h1) but when it comes to (chap10e1, chap10m1, chap10h1), my logic won't be working on those.

Isn't there any way, so that, I can distinguish the comparison between (chap1 & chap10)?

Or, Is there any alternative way of doing this? Please give me some ideas on it. Thank you!

Was it helpful?

Solution

Basically, preg_match would do just that:

$count = 0;
foreach($_POST as $k => $v)
{
    if (preg_match('/\bchap1[^\d]{0,1}/', $k)) ++$count;
}

How the pattern works:

  • \b: a word-boundary. matches chap1, but not schap, it can't be part of a bigger string
  • chap1: matches a literal string (because it's preceded by \b, this literal can't be preceded by a char, but it can be the beginning of a string, for example
  • [^\d]{0,1}: Matches anything except numbers zero or one times. so chap10 is not a match, but chap1e is

To deal with all of these "chapters" at once, try this:

$count = array();
foreach($_POST as $k => $v)
{
    if (preg_match('/\bchap(\d+)(.*)/', $k, $match))
    {
        $match[2] = $match[2] ? $match[2] : 'empty';//default value
        if (!isset($count[$match[1]])) $count[$match[1]] = array();
        $count[$match[1]][] = $match[2];
    }
}

Now this pattern is a bit more complex, but not much

  • \bchap: same as before, wourd boundary + literal
  • (\d+): Match AND GROUP all numbers (one or more, no numbers aren't accepted). We use this group as key later on ($match[1])
  • (.*): match and group the rest of the string. If there's nothing there, that's OK. If you don't want to match keys like chap1, and require something after the digits, replace the * asterisk with a plus sign

Now, I've turned the $count variable into an array, that will look like this:

array('1' => array('e1', 'a3'),
      '10'=> array('s3')
);

When $_POST looks something like this:

array(
    chap1e1 => ?,
    chap1a3 => ?,
    chap10s3=> ?
)

What you do with the values is up to you. One thing you could do is to group the key-value pairs per "chapter"

$count = array();
foreach($_POST as $k => $v)
{
    if (preg_match('/\bchap(\d+)/', $k, $match))
    {
        if (!isset($count[$match[1]])) $count[$match[1]] = array();
        $count[$match[1]][$k] = $v;//$match[1] == chap -> array with full post key->value pairs
    }
}

Note that, if this is a viable solution for you, it's not a bad idea to simplify the expression (because regex's are best kept simple), and just omit the (.*) at the end.
With the code above, to get the count of any "chap\d" param, simply use:

echo 'count 1: ', isset($count[1]) ? count($count[1]) : 0, PHP_EOL;

OTHER TIPS

you may need tweaking the reg ex code,anyway this will give a start

if (preg_match("/chap[0-9]{1,3}/i", $v, $match)) {
    $count++;
}

You can use:

$rest = substr($k, 0, 5);

and then compare your string like ($rest !== 'chap1')

I hope this works.

I have tested the below code on Execute PHP Online

<?php
    $_POST['chap1e1'] = 'test1';
    $_POST['chap10e1'] = 'test2';
    foreach($_POST as $k => $v){
    // for all types of questions of chapter 1 only
    $count = 0;
    var_dump($k);
    var_dump(strpos($k, 'chap1'));
    var_dump(strpos($k, 'chap1') !== false);
}
foreach($_POST as $k => $v){
    // for all types of questions of chapter 1 only
    //$count = 0;
    var_dump($count);
    if(strpos($k, 'chap1') !== false){
        $count++;
    }
}
echo $count;
?>

And the get the below output string(7) "chap1e1" int(0) bool(true) string(8) "chap10e1" int(0) bool(true) int(0) int(1) 2

Indicating the strpos is able to locate "chap1" in "chap10e1" but the $count total is wrong because your code always reset $count to 0 inside the foreach loop

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top