开发者

Help with regular expression and nested items

I have a class structure in PHP which I am using to allow for varying calculations of an average of marks in a teacher's markbook. I am attempting to make this as flexible as possible...

Each Assessment (A) has a mark and a weighting to count to the overall average. This object has getMark and getWeighting methods which allows be to extract the mark and the weighting.

The Assessment class is extended to create a WeightedAverage (W) object which can store many assessments. It includes an array of assessments in addition to the mark (which is unused) and the weighting. The getMark method is overridden to calculate a mark using the array of Ass开发者_运维百科essment objects (which, by nature of the OO employed, could include other weighted averages).

Finally, the Assessment class is extended to create a TopX (T) object which can store many assessments and return the average of the top 'X' assessments stored in it.

I now need to store the "algorithm" that the teacher wants to use in a database. I envisage storing it as a string that might look like this:

W(A(1,10),A(2,10),A(3,10),T(3,30,A(4,1),A(5,1),A(6,1),A(7,1),W(A(8,1),A(9,1))))

This would calculate a final result based on the weighted average of assessment 1 adjusted to 10, assessment 2 adjusted to 10, assessment 3 adjusted to 10 and then the top 3 assessments adjusted to 30 of assessments 4, 5, 6, 7 and the combined average of assessments 8 and 9, each weighted equally.

Ideally, I'd like to end up with an array that looks something like this which can then easily be translated into the objects required for the calculation.

$array [0] ['type'] = 'W'
$array [0] [0] = 'A(1,10)'
$array [0] [1] = 'A(2,10)'
$array [0] [2] = 'A(3,10)'
$array [0] [3] ['type'] = 'T'
$array [0] [3] ['params'] = '3,30'
$array [0] [3] [0] = 'A(4,1)'
$array [0] [3] [1] = 'A(5,1)'
$array [0] [3] [2] = 'A(6,1)'
$array [0] [3] [3] = 'A(7,1)'
$array [0] [3] [4] ['type'] = 'W'
$array [0] [3] [4] [0] = 'A(8,1)'
$array [0] [3] [4] [1] = 'A(9,1)'

I don't know if regular expressions are the way forward here, or whether this will require some hefty coding....

Please feel free to suggest other solutions to the problem. For now, this is still in the planning phase!


You need a simplistic parser. But I would use a regular expression still to split up the tokens more easily (otherwise you wold have more work with string functions).

$str = 'W(A(1,10),A(2,10),A(3,10),T(3,30,A(4,1),A(5,1),A(6,1),A(7,1),W(A(8,1),A(9,1))))';

preg_match_all('/[AWT()]|\d+/', $str, $token);
print_r(group($token[0]));


function group(&$t, $type="ROOT") {
    $data["type"] = $type;
    while ($token = array_shift($t)) {
       switch ($token) {
           case "A": case "W": case "T":
              $type = $token;
              break;
           case "(":
              $d = group($t, $type);
              $data[] = $d;
        // or $data[] = $type=="A" ? "A(".implode(",",array_slice($d,1)).")" : $d;
              break;
           case ")":
              return $data;
           default:
              $data[] = $token;
       }
    }
    return $data;
}

It doesn't give quite the result that you wanted. It splits up each group according to the simplistic rules:

Array
(
    [type] => ROOT
    [0] => Array
        (
            [type] => W
            [0] => Array
                (
                    [type] => A
                    [0] => 1
                    [1] => 10
                )

            [1] => Array
                (
                    [type] => A
                    [0] => 2
                    [1] => 10
                )

            [2] => Array
                (
                    [type] => A
                    [0] => 3
                    [1] => 10
                )

            [3] => Array
                (
                    [type] => T
                    [0] => 3
                    [1] => 30
                    [2] => Array
                        (
                            [type] => A
                            [0] => 4
                            [1] => 1
                        )

                    [3] => Array
                        (
                            [type] => A
                            [0] => 5
                            [1] => 1
                        )

                    [4] => Array
                        (
                            [type] => A
                            [0] => 6
                            [1] => 1
                        )

                    [5] => Array
                        (
                            [type] => A
                            [0] => 7
                            [1] => 1
                        )

                    [6] => Array
                        (
                            [type] => W
                            [0] => Array
                                (
                                    [type] => A
                                    [0] => 8
                                    [1] => 1
                                )

                            [1] => Array
                                (
                                    [type] => A
                                    [0] => 9
                                    [1] => 1
                                )

                        )

                )

        )

)

So you might actually have to travers it again, and compact the A groups again into strings. But that seems easy enough.

Or see the commented out one-liner which folds the A(x,y) tokens again:

Array
(
    [type] => ROOT
    [0] => Array
        (
            [type] => W
            [0] => A(1,10)
            [1] => A(2,10)
            [2] => A(3,10)
            [3] => Array
                (
                    [type] => T
                    [0] => 3
                    [1] => 30
                    [2] => A(4,1)
                    [3] => A(5,1)
                    [4] => A(6,1)
                    [5] => A(7,1)
                    [6] => Array
                        (
                            [type] => W
                            [0] => A(8,1)
                            [1] => A(9,1)
                        )

                )

        )

)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜