给定一个字符串创建一个带有命名键的多维数组,使用正则表达式

时间:2021-11-03 10:48:36

I'm using PHP. Given, for example, the following string:

我正在使用PHP。例如,给出以下字符串:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]|a30"

and exploding it by | I get the strings:

并通过|爆炸它我得到了字符串:

a2c4-8
a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]
a30

Now I would like to separate the digits that follow the a from all the other characters, remove the letters a and c (keep dashes, commas and square brackets) and place the results in a multidimensional array as follows:

现在我想将a后面的数字与所有其他字符分开,删除字母a和c(保留破折号,逗号和方括号)并将结果放在多维数组中,如下所示:

Array
(
    [0] => Array
        (
            [a] => 2
            [c] => 4-8
        )

    [1] => Array
        (
            [a] => 6
            [c] => 2,3-5,6[2],8[4]-10,14-21[5]
    )

    [2] => Array
        (
            [a] => 30
            [c] => 
        )

)

a is always followed by digit and after this digit there may be or may not be a c followed by other comma separated strings.

a后面总是跟着数字,在这个数字之后可能有或者可能没有c后跟其他逗号分隔的字符串。

Notice that in the resulting array the letters a and c have been removed. All other characters have been kept. I tried to modify this answer by Casimir et Hippolyte but without success.

请注意,在结果数组中,字母a和c已被删除。所有其他角色都被保留了下来。我试图通过Casimir et Hippolyte修改这个答案,但没有成功。

A plus would be avoid to add to the resulting array empty array keys (as the last [c] above).

一个加号将避免添加到结果数组空数组键(如上面的最后一个[c])。

1 个解决方案

#1


1  

Consider the following solution using preg_match_all function with named submasks((?P<a>)...) and PREG_SET_ORDER flag, array_map, array_filter, array_column(available since PHP 5.5) and trim functions:

考虑以下解决方案,使用preg_match_all函数和命名子掩码((?P )...)和PREG_SET_ORDER标志,array_map,array_filter,array_column(自PHP 5.5起可用)和trim函数:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]|a30";
$parts = explode("|", $str);

$result = array_map(function ($v) {
    preg_match_all("/(?P<a>a\d+)?(?P<c>c[0-9-\[\]]+)?/", $v, $matches, PREG_SET_ORDER);
    $arr = [];
    $a_numbers = array_filter(array_column($matches, "a"));
    $c_numbers = array_filter(array_column($matches, "c"));
    if (!empty($a_numbers)) {
        $arr['a'] = array_map(function($v){ return trim($v, 'a'); }, $a_numbers)[0];
    }
    if (!empty($c_numbers)) {
        $arr['c'] = implode(",", array_map(function($v){ return trim($v, 'c'); }, $c_numbers));
    }

    return $arr;
}, $parts);

print_r($result);

The output:

输出:

Array
(
    [0] => Array
        (
            [a] => 2
            [c] => 4-8
        )

    [1] => Array
        (
            [a] => 6
            [c] => 2,3-5,6[2],8[4]-10,14-21[5]
        )

    [2] => Array
        (
            [a] => 30
        )
)

P.S. "empty array keys" are also omitted

附: “空数组键”也被省略

#1


1  

Consider the following solution using preg_match_all function with named submasks((?P<a>)...) and PREG_SET_ORDER flag, array_map, array_filter, array_column(available since PHP 5.5) and trim functions:

考虑以下解决方案,使用preg_match_all函数和命名子掩码((?P )...)和PREG_SET_ORDER标志,array_map,array_filter,array_column(自PHP 5.5起可用)和trim函数:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]|a30";
$parts = explode("|", $str);

$result = array_map(function ($v) {
    preg_match_all("/(?P<a>a\d+)?(?P<c>c[0-9-\[\]]+)?/", $v, $matches, PREG_SET_ORDER);
    $arr = [];
    $a_numbers = array_filter(array_column($matches, "a"));
    $c_numbers = array_filter(array_column($matches, "c"));
    if (!empty($a_numbers)) {
        $arr['a'] = array_map(function($v){ return trim($v, 'a'); }, $a_numbers)[0];
    }
    if (!empty($c_numbers)) {
        $arr['c'] = implode(",", array_map(function($v){ return trim($v, 'c'); }, $c_numbers));
    }

    return $arr;
}, $parts);

print_r($result);

The output:

输出:

Array
(
    [0] => Array
        (
            [a] => 2
            [c] => 4-8
        )

    [1] => Array
        (
            [a] => 6
            [c] => 2,3-5,6[2],8[4]-10,14-21[5]
        )

    [2] => Array
        (
            [a] => 30
        )
)

P.S. "empty array keys" are also omitted

附: “空数组键”也被省略