有没有一种很好的方法来迭代字符串的字符? 我希望能够对字符串的字符执行
foreach
、array_map
、array_walk
、array_filter
等操作。
类型转换/杂耍并没有让我有任何进展(将整个字符串作为数组的一个元素),我发现的最佳解决方案就是简单地使用 for 循环来构造数组。 感觉应该有更好的东西。 我的意思是,如果你可以索引它,你不应该也能够迭代吗?
这是我最好的了
function stringToArray($s)
{
$r = array();
for($i=0; $i<strlen($s); $i++)
$r[$i] = $s[$i];
return $r;
}
$s1 = "textasstringwoohoo";
$arr = stringToArray($s1); //$arr now has character array
$ascval = array_map('ord', $arr); //so i can do stuff like this
$foreach ($arr as $curChar) {....}
$evenAsciiOnly = array_filter( function($x) {return ord($x) % 2 === 0;}, $arr);
有没有:
A) 一种使字符串可迭代的方法
B)从字符串构建字符数组的更好方法(如果是这样,另一个方向怎么样?)
我觉得我在这里错过了一些明显的东西。
如果您的字符串包含 only ASCII(即“英语”)字符,则使用 str_split。
$str = 'some text';
foreach (str_split($str) as $char) {
var_dump($char);
}
如果您的字符串可能包含Unicode(即“非英语”)字符,那么您必须使用mb_str_split。
$str = 'μυρτιὲς δὲν θὰ βρῶ';
foreach (mb_str_split($str) as $char) {
var_dump($char);
}
迭代字符串:
for ($i = 0; $i < strlen($str); $i++){
echo $str[$i];
}
如果您的字符串采用 Unicode,则应使用
preg_split
和 /u
修饰符
来自 php 文档中的注释:
function mb_str_split( $string ) {
# Split at all position not after the start: ^
# and not before the end: $
return preg_split('/(?<!^)(?!$)/u', $string );
}
如果您只需要访问 $s1,您也可以像数组一样访问它:
$s1 = "hello world";
echo $s1[0]; // -> h
大多数答案都忘记了非英文字符!!!
strlen
计算字节,而不是字符,这就是为什么它是这样的,它的同级函数可以很好地处理英文字符,因为英文字符在 UTF-8 和 ASCII 编码中都存储在 1 个字节中,您需要使用 多字节字符串功能mb_*
这适用于以 UTF-8
编码的any 字符
// 8 characters in 12 bytes
$string = "abcdأبتث";
$charsCount = mb_strlen($string, 'UTF-8');
for($i = 0; $i < $charsCount; $i++){
$char = mb_substr($string, $i, 1, 'UTF-8');
var_dump($char);
}
这个输出
string(1) "a"
string(1) "b"
string(1) "c"
string(1) "d"
string(2) "أ"
string(2) "ب"
string(2) "ت"
string(2) "ث"
对于那些正在寻找在 php 中迭代字符串的最快方法的人,我准备了基准测试。
第一种方法是通过在括号中指定其位置并将字符串视为数组来直接访问字符串字符:
$string = "a sample string for testing";
$char = $string[4] // equals to m
我自己认为后者是最快的方法,但我错了。
与第二种方法(在接受的答案中使用)一样:
$string = "a sample string for testing";
$string = str_split($string);
$char = $string[4] // equals to m
这种方法会更快,因为我们使用的是 real 数组,而不是假设它是一个数组。
调用上述每个方法的最后一行
1000000
次会得到以下基准测试结果:
使用字符串[i]
0.24960017204285 Seconds
使用str_split
0.18720006942749 Seconds
这意味着第二种方法要快得多。
从@SeaBrightSystems回答扩展,你可以尝试这个:
$s1 = "textasstringwoohoo";
$arr = str_split($s1); //$arr now has character array
嗯...没必要把事情复杂化。基础知识总是很好用。
$string = 'abcdef';
$len = strlen( $string );
$x = 0;
前进方向:
while ( $len > $x ) echo $string[ $x++ ];
输出:
abcdef
反向:
while ( $len ) echo $string[ --$len ];
输出:
fedcba
// Unicode Codepoint Escape Syntax in PHP 7.0
$str = "cat!\u{1F431}";
// IIFE (Immediately Invoked Function Expression) in PHP 7.0
$gen = (function(string $str) {
for ($i = 0, $len = mb_strlen($str); $i < $len; ++$i) {
yield mb_substr($str, $i, 1);
}
})($str);
var_dump(
true === $gen instanceof Traversable,
// PHP 7.1
true === is_iterable($gen)
);
foreach ($gen as $char) {
echo $char, PHP_EOL;
}
根据您的需求/“字符”的定义,保持多字节“簇”完整可能是最有帮助的。
从 PHP8.2.18 开始,通过
grapheme_
函数实现了对多组件表情符号的更好处理。
代码:(演示)
$text = 'Hey 🙇♂️ boy';
for ($i = 0, $len = grapheme_strlen($text); $i < $len; ++$i) {
echo grapheme_substr($text, $i, 1) . "\n";
}
输出:
H
e
y
🙇♂️
b
o
y
即使使用
mb_
函数也会产生:(Demo)
H
e
y
🙇
♂
️
b
o
y
为了简化此任务,PHP8.4 在
grapheme_
系列中添加了一个新的分割函数:grapheme_split()。
代码:
$text = 'Hey 🙇♂️ boy';
foreach (grapheme_split($text) as $g) {
echo $g . "\n";
}