【问题标题】:PHP - iterate on string charactersPHP - 迭代字符串字符
【发布时间】:2011-06-03 19:34:31
【问题描述】:

有没有很好的方法来迭代字符串的字符?我希望能够对字符串的字符执行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)从字符串构建字符数组的更好方法(如果是这样,另一个方向呢?)

我觉得我在这里遗漏了一些明显的东西。

【问题讨论】:

  • 也许你应该多说一些你正在努力完成的事情......似乎有更好的方法可以使用普通的字符串操作来做到这一点。
  • 这里没有真正的目标。只是我在玩的一个好奇心。似乎很奇怪,即使您可以对无法迭代的字符串进行索引。我什至想不出有意义的示例用途,但我仍然想知道是否有某种方法可以在不显式构造字符数组的情况下迭代字符串字符
  • 这很好,显然我的例子很肤浅。即 - 从这个意义上说,你对array_filter 所做的大多数事情都可以用字符串或正则表达式函数更好地完成
  • 解决projecteuler.net/problem=20 可能是一个示例(尽管有些做作)。
  • 一个注释,关于 for($i=0; $i

标签: php string character-arrays


【解决方案1】:

第一步:使用str_split函数将字符串转换为数组

$array = str_split($your_string);

第 2 步:循环遍历新创建的数组

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

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

【讨论】:

  • @jon_darkstar 我不了解您的应用程序,但请注意数组中的每个条目都有很大的开销(4 字节 IIRC)。跳过那个,它“相当”得多:nikic.github.com/2011/12/12/…
  • str_split() will split into bytes, rather than characters when dealing with a multi-byte encoded string. - 所以str_split 不能使用Unicode
  • mb_str_split 将是多字节等价物。 $array = mb_str_split($your_string);
【解决方案2】:

迭代字符串:

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

【讨论】:

  • 这似乎是一个更好的答案,因为它回答了问题——即如何迭代字符串而不是“转换为数组”。
  • 哈哈!!!!!一切@OmarTariq。这比提供的答案要有效得多。
  • 请注意,您在每次迭代中都调用了strlen()。这不是一件可怕的事情,因为 PHP 已经预先计算了长度,但仍然是一个函数调用。如果您需要速度,最好在开始循环之前将其保存在变量中。
  • 这对多字节字符串不好,因为这里我们得到的是字节偏移量,而不是符号
  • @OmarTariq “这就是答案。这个世界怎么了?” ....这个世界的错误在于这个世界除了英语还有其他语言,正如 alvery 所说,这个函数将迭代字符串中的字节,而不是字符。
【解决方案3】:

如果你的字符串是 Unicode,你应该使用 preg_split/u 修饰符

来自 php 文档中的 cmets:

function mb_str_split( $string ) { 
    # Split at all position not after the start: ^ 
    # and not before the end: $ 
    return preg_split('/(?<!^)(?!$)/u', $string ); 
} 

【讨论】:

  • 对于多字节字符串,mb_split 更可靠。
  • 需要引用@Lux
  • @mickmackusa 已经好几年了(这些天你可能应该使用 stdlib mb_str_split 如果你在 PHP ≥7.4 上),我真的不记得我的意思了在那里,但我的猜测是带有/.../u 的 preg_split 仅是 UTF-8(不是 'Unicode',正如 OP 所说),而mb_split 允许任意编码(此外,mb_split 明确设计用于正则表达式拆分多字节字符串,所以它可能有一些额外的优化等等?一般来说,因为它是专门构建的,我的默认假设是它比 /u PCRE 扩展更可靠和/或更完整)
  • 我个人不知道mb_str_split()preg_split('//u', $string) 之间的任何区别。我只是说,重要的是我们不要基于假设而使潜在的错误主张永久化。如果可以证明一种技术不如另一种技术,我们应该能够证实这一事实。
  • 是的!谢谢你打电话给我。不幸的是,我编辑原始评论为时已晚,但希望后续能澄清我的意思;来自herehere 的信息,因为我在上一条评论中点击了charlimit。
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    对于那些正在寻找在 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

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

    【讨论】:

      【解决方案6】:

      从@SeaBrightSystems 的答案扩展而来,你可以试试这个:

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

      【讨论】:

      • 我不同意,这个答案确实增加了价值,它提供了 str_split 如何在 PHP 应用程序中工作的工作示例。 @SeaBrightSystems 只是指向文档的链接,举例来说,当人们试图查看函数如何工作时,这有时并没有太大帮助。否则大多数 SO 答案将只是链接到 php.net
      【解决方案7】:

      嗯...没有必要让事情复杂化。基础知识总是很好。

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

      前进方向:

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

      输出:abcdef

      反向:

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

      输出:fedcba

      【讨论】:

        【解决方案8】:

        大部分答案都忘记了非英文字符!!!

        strlen 计算 BYTES,而不是字符,这就是它的原因,它的兄弟函数适用于英文字符,因为英文字符在 UTF-8 和 ASCII 编码中都存储在 1 个字节中,您需要使用 @ 987654321@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);
        }
        

        这个outputs

        string(1) "a"
        string(1) "b"
        string(1) "c"
        string(1) "d"
        string(2) "أ"
        string(2) "ب"
        string(2) "ت"
        string(2) "ث"
        

        【讨论】:

          【解决方案9】:
          // 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;
          }
          

          【讨论】:

            猜你喜欢
            • 2012-10-23
            • 2014-04-21
            • 2014-04-04
            • 2020-12-25
            • 2013-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多