PHP-迭代字符串字符


119

有没有一种很好的方法可以迭代字符串的字符?我希望能够做到foreacharray_maparray_walkarray_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)从字符串构建字符数组的更好方法(如果可以,那么其他方向呢?)

我觉得我在这里缺少明显的东西。


也许您应该多说一点您要完成的事情……似乎可以使用常规的字符串操作来实现此目的的更好方法。
Vinay Pai

1
这里没有真正的目标。只是出于好奇。似乎很奇怪,即使您可以索引字符串也无法迭代。我不知所措,甚至想不出有意义的示例用法,但我仍然想知道是否有某种方法可以在不显式构造字符数组的情况下迭代字符串字符
jon_darkstar 2011年

多数民众赞成在好点,但显然我的例子很浅。即- array_filter使用字符串或reg-ex函数可以更好地完成这种意义上的任何事情
jon_darkstar

解决projecteuler.net/problem=20可能是一个示例(尽管有些人为)。
尼克·爱德华兹

需要注意的是,对于for($ i = 0; $ i <strlen($ s); $ i ++),我将在循环之前将strlen($ s)存储在变量中,这样,您将调用strlen()的次数不会超过1次
Amin

Answers:


176

步骤1:使用str_split函数将字符串转换为数组

$array = str_split($your_string);

步骤2:遍历新创建的数组

foreach ($array as $char) {
 echo $char;
}

您可以查看PHP文档以获得更多信息: str_split


哇 是的,就是这样。当然,内爆可以朝另一个方向发展。我会尽快接受,除非有人可以展示一种直接进行迭代的方法
jon_darkstar 2011年

@jon_darkstar我不知道您的应用程序,但请注意,数组中的每个条目都有相当大的开销(4字节IIRC)。跳过这一点,更多的是“相当”的方式:nikic.github.com/2011/12/12/…–
Daan Timmer

str_split() will split into bytes, rather than characters when dealing with a multi-byte encoded string.-因此str_split无法使用Unicode
快乐

84

迭代字符串:

for ($i = 0; $i < strlen($str); $i++){
    echo $str[$i];
}

7
这似乎是一个更好的答案,因为它回答了问题-即如何遍历字符串而不是“转换为数组”。
罗宾·安德鲁斯

2
大声笑!!!!!一切@OmarTariq。这比提供的答案有效得多。
0x476f72616e

5
请注意,您strlen()在每次迭代中都在调用。这不是一件可怕的事情,因为PHP已经预先计算了长度,但是仍然是一个函数调用。如果需要速度,最好在开始循环之前将其保存在变量中。
Vilx-

2
这对多字节字符串
不利

2
@OmarTariq “这就是答案。世界出了什么问题?” ....世界的错误之处在于,世界上除了英语以外,还有其他语言,如alvery所说,此功能将迭代字符串中的字节,而不是字符。
会计师,

20

如果你的字符串是用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 ); 
} 

1
对于多字节字符串,mb_split更可靠。
艾丽卡

12

如果只需要访问$ s1,则也可以像访问数组一样访问它:

$s1 = "hello world";
echo $s1[0]; // -> h

6

从@SeaBrightSystems答案展开后,您可以尝试以下操作:

$s1 = "textasstringwoohoo";
$arr = str_split($s1); //$arr now has character array

我不同意,这个答案确实增加了价值,它给出了str_split如何在PHP应用程序中工作的工作示例。@SeaBrightSystems只是链接到文档,例如,当一个人试图查看某个功能如何工作时,有时并没有太大帮助。否则,大多数的答案就是链接到php.net
kurdtpage '16

6

对于那些正在寻找在php中迭代字符串的最快方法的人,Ive准备了基准测试。
第一种方法,您可以通过在方括号中指定其位置并将字符串视为数组来直接访问字符串字符:

$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

此方法将更快,因为我们使用的是实数数组,而不是假设一个数组。

1000000多次调用上述每种方法的最后一行会导致这些基准测试结果:

使用字符串[i]
0.24960017204285 Seconds

使用str_split
0.18720006942749 Seconds

这意味着第二种方法更快。


3

嗯...没有必要使事情复杂化。基础总是很出色。

    $string = 'abcdef';
    $len = strlen( $string );
    $x = 0;

前进方向:

while ( $len > $x ) echo $string[ $x++ ];

输出: abcdef

反向:

while ( $len ) echo $string[ --$len ];

输出: fedcba


2
// 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;
}

我很惊讶这个答案只有1个投票:(这是这里最/唯一可靠的答案
会计师

1

大多数答案都忘记了非英文字符!

strlen计算字节数,而不是字符,这就是为什么,它的同级函数对英文字符可以正常工作,因为英文字符以UTF-8和ASCII编码都存储在1个字节中,因此您需要使用多字节字符串函数 mb_*

这将与任何编码为UTF-8

// 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) "ث"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.