对带有preg_split()的字符串进行两次正则表达式扫描: (Demo)
$digits = preg_split("/\D+/", $str, 0, PREG_SPLIT_NO_EMPTY);
$symbols = preg_split("/\d+/", $str, 0, PREG_SPLIT_NO_EMPTY);
对带有preg_split()的字符串进行一次正则表达式扫描: (Demo)
foreach (preg_split("/(\d+)/", $str, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $string) {
if (ctype_digit($string)) {
$digits[] = $string;
} else {
$symbols[] = $string;
}
}
对带有preg_match_all()的字符串进行一次正则表达式扫描: (Demo)
preg_match_all("/(\d+)|(\D+)/", $str, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
if ($match[1] !== '') {
$digits[] = $match[1];
} else {
$symbols[] = $match[2];
}
}
在大多数情况下,数据量很小,效率不值得进行基准测试。如果您的项目确实如此,请选择您认为最容易阅读和维护的技术。
说明
基于正则表达式的解决方案是从输入字符串中提取所需子字符串的唯一有效/直接的方法。
我们只能假设您的输入字符串仅由数字和符号组成(没有其他字符)。如果还有其他字符,则需要调整模式。
在捕获数字时,有四种基本模式可供选择:\d+、[^\D]、[0-9]+、[^-+*/]+ 所有四种模式都采用相同数量的“步数”,因此决定因素是模式简洁和\d+ 获胜。
通过捕获符号,有四种基本模式:\D、[^\d]、[^0-9]、[-+/*] 所有四种模式都采用相同数量的“步数”,所以再次决定因素是模式的简洁性和\D 获胜。
为了进行最佳测试,我将使用 $str = "50+16-0*387/2+49"; 作为我的输入,因为它包含一个零和多位整数。
为了可能因计票而有偏见的研究人员的利益,对 Sahil 的回答进行了批评:
-
[+-\/\*] 正在教授不良品格课程建设。此模式is saying 匹配以下列出的 6 个字符中的任何一个(但此任务只需要 4 个符号):
- 从连字符到正斜杠的任何字符(
+、,、-、.、/)
- 字面星号(不需要转义)
换句话说,字符类中的连字符没有按字面意思处理,它创建了一系列可接受的字符。
-
使用array_map() 但忽略其返回值表示该函数使用不当。使用array_walk() 会更明智,但必要的语法更冗长且难以阅读。 array_filter() 或 array_reduce() 也可用于将过滤后的数组返回到相应的结果变量,但这意味着对相同的数据执行两个循环。 foreach()(作为单次传递)将是填充两个结果数组的最简洁方式。
-
preg_split() 调用很容易生成空元素,因为没有使用 PREG_SPLIT_NO_EMPTY 标志。