将带有简单标记的字符串分解为数组的最佳方法是什么?
What is the best way to explode a string with simple markup into an array?
在 PHP 中,我想找出最好的方法来获取其中包含一些简单标签的字符串,并将其分解为一个多维数组,每个索引包含另外两个包含项目 [=11 的数组=] 和 text
。如果没有特殊标签,tags
将是 null
。如果字符串的一部分存在一个(或多个)标签,tags
将包含所有相关标签指示符的 space 分隔列表。
示例:
字符串
The __**quick** brown__ fox jumped __over the__ lazy dog.
处理数组
[
[
'tags' => null,
'text' => 'The ',
],
[
'tags' => '__ **',
'text' => 'quick',
],
[
'tags' => '__',
'text' => ' brown',
],
[
'tags' => null,
'text' => ' fox jumped ',
],
[
'tags' => '__',
'text' => 'over the',
],
[
'tags' => null,
'text' => ' lazy dog.',
],
]
我正在努力思考什么是最好的方法。这个概念看起来很简单,但我想得越多,我就越不知道如何实现它。在 foreach
中使用 preg_match
函数的某种组合是最好的方法,还是有其他选择?任何指向正确方向的帮助将不胜感激。
恶魔并不像画的那么黑
$str = 'The __**quick** brown__ fox jumped __over the__ lazy dog.';
$t = array_map(function($i) {
$i = preg_split('/[^ A-Za-z]+\K/', $i,2);
if (count($i) == 1) array_unshift($i, null);
return $i;
}, preg_split('/[A-Za-z.,]\K(?=[^A-Za-z.,])/', $str));
print_r($t);
因为您有叠层标记,所以您需要一个堆栈来跟踪叠层级别。没有办法直接用正则表达式来做到这一点,所以只迭代字符串符号可能更容易。
作为开始:
print_r(process("The __**quick** brown__ fox jumped __over the__ lazy dog."));
function process($str) {
$str = '~~'.$str.'~~';
$sz = strlen($str);
$res = array();
$stack = array();
$text = '';
for($n = 0; $n < $sz; $n++) {
if(strpos('*_~', $c = $str[$n]) === false) {
$text .= $c;
continue;
}
if($text) {
$res[] = array('text' => $text, 'tags' => implode(" ", array_slice($stack, 1)));
$text = '';
}
$c .= $str[$n++];
$c == end($stack) ? array_pop($stack) : $stack[] = $c;
}
return $res;
}
输出:
Array
(
[0] => Array
(
[text] => The
[tags] =>
)
[1] => Array
(
[text] => quick
[tags] => __ **
)
[2] => Array
(
[text] => brown
[tags] => __
)
[3] => Array
(
[text] => fox jumped
[tags] =>
)
[4] => Array
(
[text] => over the
[tags] => __
)
[5] => Array
(
[text] => lazy dog.
[tags] =>
)
)
一些注意事项:
- 此代码假定输入是正确的。它不执行任何检查。
- 在内部,整个字符串被封装到'~~'标记中。这样,字符串处理以 'end of tag' 条件结束,最后一个待处理的文本块被正确地附加到结果集中。 (请称我为懒狗,因为我这样做了。)然而,这个标记并没有注入到最终结果中。
在 PHP 中,我想找出最好的方法来获取其中包含一些简单标签的字符串,并将其分解为一个多维数组,每个索引包含另外两个包含项目 [=11 的数组=] 和 text
。如果没有特殊标签,tags
将是 null
。如果字符串的一部分存在一个(或多个)标签,tags
将包含所有相关标签指示符的 space 分隔列表。
示例:
字符串
The __**quick** brown__ fox jumped __over the__ lazy dog.
处理数组
[
[
'tags' => null,
'text' => 'The ',
],
[
'tags' => '__ **',
'text' => 'quick',
],
[
'tags' => '__',
'text' => ' brown',
],
[
'tags' => null,
'text' => ' fox jumped ',
],
[
'tags' => '__',
'text' => 'over the',
],
[
'tags' => null,
'text' => ' lazy dog.',
],
]
我正在努力思考什么是最好的方法。这个概念看起来很简单,但我想得越多,我就越不知道如何实现它。在 foreach
中使用 preg_match
函数的某种组合是最好的方法,还是有其他选择?任何指向正确方向的帮助将不胜感激。
恶魔并不像画的那么黑
$str = 'The __**quick** brown__ fox jumped __over the__ lazy dog.';
$t = array_map(function($i) {
$i = preg_split('/[^ A-Za-z]+\K/', $i,2);
if (count($i) == 1) array_unshift($i, null);
return $i;
}, preg_split('/[A-Za-z.,]\K(?=[^A-Za-z.,])/', $str));
print_r($t);
因为您有叠层标记,所以您需要一个堆栈来跟踪叠层级别。没有办法直接用正则表达式来做到这一点,所以只迭代字符串符号可能更容易。
作为开始:
print_r(process("The __**quick** brown__ fox jumped __over the__ lazy dog."));
function process($str) {
$str = '~~'.$str.'~~';
$sz = strlen($str);
$res = array();
$stack = array();
$text = '';
for($n = 0; $n < $sz; $n++) {
if(strpos('*_~', $c = $str[$n]) === false) {
$text .= $c;
continue;
}
if($text) {
$res[] = array('text' => $text, 'tags' => implode(" ", array_slice($stack, 1)));
$text = '';
}
$c .= $str[$n++];
$c == end($stack) ? array_pop($stack) : $stack[] = $c;
}
return $res;
}
输出:
Array
(
[0] => Array
(
[text] => The
[tags] =>
)
[1] => Array
(
[text] => quick
[tags] => __ **
)
[2] => Array
(
[text] => brown
[tags] => __
)
[3] => Array
(
[text] => fox jumped
[tags] =>
)
[4] => Array
(
[text] => over the
[tags] => __
)
[5] => Array
(
[text] => lazy dog.
[tags] =>
)
)
一些注意事项:
- 此代码假定输入是正确的。它不执行任何检查。
- 在内部,整个字符串被封装到'~~'标记中。这样,字符串处理以 'end of tag' 条件结束,最后一个待处理的文本块被正确地附加到结果集中。 (请称我为懒狗,因为我这样做了。)然而,这个标记并没有注入到最终结果中。