Home » Php » php – Convert complex string to array, multiple times by multiple delimiters

php – Convert complex string to array, multiple times by multiple delimiters

Posted by: admin February 25, 2020 Leave a comment

Questions:

I have a string

Label 1|80|default
Label 2|100|default
---
Frontend|80|red
Backend|20|red
---
Another Item 1|20|blue
Another Item 2|20|blue
-
And another Item|20|blue

which should be converted to the following array

Array
(
[0] => Array
    (
        [items] => Array
            (
                [0] => Array
                    (
                        [label] => Label 1
                        [value] => 80
                        [color] => default
                    )

                [1] => Array
                    (
                        [label] => Label 2
                        [value] => 100
                        [color] => default
                    )

            )

    )

[1] => Array
    (
        [items] => Array
            (
                [0] => Array
                    (
                        [label] => Frontend
                        [value] => 80
                        [color] => red
                    )

                [1] => Array
                    (
                        [label] => Backend
                        [value] => 20
                        [color] => red
                    )

            )

    )

[2] => Array
    (
        [items] => Array
            (
                [0] => Array
                    (
                        [label] => And another Item
                        [value] => 20
                        [color] => blue
                    )

            )

    )
)

to be converted into json:

[{"items":[{"label":"Label 1","value":"80","color":"default"},{"label":"Label 2","value":"100","color":"default"}]},{"items":[{"label":"Frontend","value":"80","color":"red"},{"label":"Backend","value":"20","color":"red"}]},{"items":[{"label":"And another Item","value":"20","color":"blue"}]}]

Currently, my way of doing that string splitting to multiple arrays seems a bit complicated to me. At least, it is hard to read.

protected function convertPartsToObject($parts): array
{
    $return = [];
    $arr1 = explode("---", trim($parts));
    foreach ($arr1 as $arr1Item) {
        $arr2 = explode("-", trim($arr1Item));
        foreach ($arr2 as $arr2Item) {
            $arr3 = explode("\n", trim($arr2Item));
            $group = [];
            foreach ($arr3 as $arr3Item) {
                $arr4 = explode("|", trim($arr3Item));
                $item = [
                    'label' => $arr4[0],
                    'value' => $arr4[1],
                    'color' => $arr4[2]
                ];
                $group['items'][] = $item;
            }
        }
        $return[] = $group;
    }
    return $return;
}

Question:

Is there a better / more readable way to convert strings by multiple delimiters to an associative array? Maybe with a nested regex?


Background, just as an info:
This is part of a content management system, where I need some data as json in frontend (for react). And I don’t want the editors to learn the json syntax…

How to&Answers:

This is an alternative to your current code. Instead of the nested explode() it just splits the input into lines and then processes the lines. For --- it just adds the current data into the result, - removes the current stored data(not sure if it should), else it extracts the data (I’ve used the ability to explode to an associative array as a shorthand, depends if you like it or not you can use your current method)…

function convertPartsToObject ( $parts ) : array {
    $return = [];
    $buffer = [];
    foreach ( explode( PHP_EOL, $parts ) as $line ) {
        if ( trim($line) == "---" ) {
            $return[]['items'] = $buffer;
            $buffer =  [];
        }
        elseif ( trim($line) == "-" ) {
            $buffer = [];
        }
        else    {
            [$arr4['label'], $arr4['value'], $arr4['color']] = explode("|", trim($line));
            $buffer[] = $arr4;
        }
    }
    // Add last items
    $return[]['items'] = $buffer;

    return $return;
}