【问题标题】:Getting the first character of a string with $str[0]使用 $str[0] 获取字符串的第一个字符
【发布时间】:2010-12-30 15:15:18
【问题描述】:

我想获取字符串的第一个字母,我注意到$str[0] 效果很好。我只是不确定这是否是“好习惯”,因为该符号通常与数组一起使用。这个特性似乎没有很好的记录,所以我求助于你们告诉我是否可以 - 在所有方面 - 使用这个符号?

或者我应该坚持使用好的 ol'substr($str, 0, 1)

另外,我注意到花括号 ($str{0}) 也可以。这是怎么回事?

【问题讨论】:

  • 加 1 表示 "good ol' substr($str, 0, 1)"。

标签: php string substring


【解决方案1】:

自 PHP 5.3.0 起,{} 语法已弃用。建议使用方括号。

【讨论】:

  • docs.php.net/language.types.string : Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. However, this syntax is deprecated as of PHP 5.3.0. Use square brackets instead, such as $str[42].
  • @VolkerK:在您提供的链接中,我注意到他们删除了他们只留下的 PHP 手册上的注释:Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. 所以我想知道他们是否决定不再推荐使用 {}自 PHP 6 起
  • @MarcoDemaio 该链接现在告诉 MichaelMorton 所说的内容。
  • “未表示弃用” - 事实上,弃用消息已在修订版 304518 中删除 - The curly-brackets-string-index-accessor-syntax does not emit any deprecation notice, although the original notice have been on and off for PHP 5.x, it does not in the current version, thrus we should not label it as deprecated. Related to bug #52254 - svn.php.net/repository/phpdoc/en/trunk/language/types/…
  • 今天(2018 年 5 月 10 日),引用了点赞的 PHP docs:Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. 似乎这种语法会保留一段时间。
【解决方案2】:

是的。字符串可以看作是字符数组,访问数组位置的方法是使用[]运算符。通常使用$str[0] 完全没有问题(而且我很确定它比substr() 方法快得多)。

这两种方法只有一个警告:它们将获得第一个 byte,而不是第一个 character。如果您使用多字节编码(例如 UTF-8),这一点很重要。如果你想支持它,请使用mb_substr()。可以说,这些天你应该总是假设多字节输入,所以这是最好的选项,但它会稍微慢一些。

【讨论】:

  • PHP $str[0] 是否考虑到可以有 2Byte 长的字符? UTF之类的? (即使 substr() 也无济于事!)
  • 如果你想更加安全,你应该使用mb_substr($str, 0, 1, 'utf-8'),这样你就不会截断多字节字符串。
  • 虽然这比substr($str, 0, 1)更短且更容易记住,但这会让阅读代码的人感到困惑。
  • 方括号和 substr() 之间的选择很大程度上是一个偏好问题,但请注意,当应用于空字符串时,结果会有所不同。如果 $s = "" 那么 $s[] === "",但是 substr($s, 0, 1) === false。
  • 如果 $s = "" 那么 $s[0] 将生成一个“注意:未初始化的字符串偏移量:0”,而 substr($s, 0, 1) 不会。
【解决方案3】:

假设您只想要 $_POST 的一部分中的第一个字符,我们将其称为“类型”。并且 $_POST['type'] 当前是“控制”。如果在这种情况下,如果您使用$_POST['type'][0]substr($_POST['type'], 0, 1),您将得到C

但是,如果客户端要修改他们发送给您的数据,例如从 typetype[],然后发送 'Control' 和 'Test' 作为该数组的数据,$_POST['type'][0] 将现在返回 Control 而不是 Csubstr($_POST['type'], 0, 1) 只会失败。

所以是的,使用$str[0] 可能会出现问题,但这取决于周围的情况。

【讨论】:

  • 作为一个旁注来规避这个特定问题,在任何一种情况下,都应该始终执行数据验证。 if (true === is_string($_POST['type']))
【解决方案4】:

我唯一的疑问是这种技术在多字节字符串上的适用性,但如果这不是考虑因素,那么我怀疑你已经被覆盖了。 (如果有疑问,mb_substr() 似乎是一个明显安全的选择。)

但是,从大局的角度来看,我想知道您需要多久访问一次字符串中的第 'n' 个字符,这是一个关键的考虑因素。

【讨论】:

    【解决方案5】:

    如果是多字节(unicode)字符串,使用str[0] 可能会导致问题。 mb_substr() 是一个更好的解决方案。例如:

    $first_char = mb_substr($title, 0, 1);
    

    这里有一些细节:Get first character of UTF-8 string

    【讨论】:

    • 感谢您提供此解决方案!如果第一个字符是 unicode,[] 将不起作用
    【解决方案6】:
    $str = 'abcdef';
    echo $str[0];                 // a
    

    【讨论】:

    • -1; OP的问题是这种语法是否是一种不好的做法,而您的回应是……重复语法,没有任何评论?这不是答案。
    【解决方案7】:

    它会因资源而异,但您可以运行下面的脚本并亲自查看;)

    <?php
    $tests = 100000;
    
    for ($i = 0; $i < $tests; $i++)
    {
        $string = md5(rand());
        $position = rand(0, 31);
    
        $start1 = microtime(true);
        $char1 = $string[$position];
        $end1 = microtime(true);
        $time1[$i] = $end1 - $start1;
    
        $start2 = microtime(true);
        $char2 = substr($string, $position, 1);
        $end2 = microtime(true);
        $time2[$i] = $end2 - $start2;
    
        $start3 = microtime(true);
        $char3 = $string{$position};
        $end3 = microtime(true);
        $time3[$i] = $end3 - $start3;
    }
    
    $avg1 = array_sum($time1) / $tests;
    echo 'the average float microtime using "array[]" is '. $avg1 . PHP_EOL;
    
    $avg2 = array_sum($time2) / $tests;
    echo 'the average float microtime using "substr()" is '. $avg2 . PHP_EOL;
    
    $avg3 = array_sum($time3) / $tests;
    echo 'the average float microtime using "array{}" is '. $avg3 . PHP_EOL;
    ?>
    

    一些参考编号(在旧的 CoreDuo 机器上)

    $ php 1.php 
    the average float microtime using "array[]" is 1.914701461792E-6
    the average float microtime using "substr()" is 2.2536706924438E-6
    the average float microtime using "array{}" is 1.821768283844E-6
    
    $ php 1.php 
    the average float microtime using "array[]" is 1.7251944541931E-6
    the average float microtime using "substr()" is 2.0931363105774E-6
    the average float microtime using "array{}" is 1.7225742340088E-6
    
    $ php 1.php 
    the average float microtime using "array[]" is 1.7293763160706E-6
    the average float microtime using "substr()" is 2.1037721633911E-6
    the average float microtime using "array{}" is 1.7249774932861E-6
    

    似乎使用[]{} 运算符或多或少是相同的。

    【讨论】:

    • 不错的测试!来自 3 岁 Xeon 的一些数字:使用“array[]”的平均浮点微时间是 2.2427082061768E-7 使用“substr()”的平均浮点微时间是 3.9647579193115E-7 使用“array{}”的平均浮点微时间是2.1522283554077E-7
    • 为了获得准确的测量结果,恕我直言,您应该更好地在循环外执行 microtime,并且不要在同一个循环中混合使用不同的方法。
    • 不在同一循环中混合执行 testAtestB 意味着您能够检测到例如事实上testB 是缓存杀手,而testA 是缓存友好的。当它们都在同一个循环中时,它们被测量为具有完全相同的时间,因为testB 污染了testA 的缓存。
    • 类似地,我会避免在测试循环中生成字符串或随机数,并在附近的数组中准备好它们。
    • -1;撇开有问题的计时机制不谈(对许多操作计时比一次计时要好;我在读到这篇文章时担心,只是执行microtime() 调用所花费的时间会弥补大部分时间差,尽管实验上这似乎不是真的),没有理由关心这里的微小速度差异。不到百万分之一秒;这永远什么时候重要?
    【解决方案8】:

    作为一个凡人,我会坚持使用$str[0]。就我而言,一目了然地掌握$str[0]的含义比substr($str, 0, 1)要快。这可能归结为偏好问题。

    就性能而言,配置文件配置文件。 :) 或者您可以查看 PHP 源代码...

    【讨论】:

      【解决方案9】:

      我以前也使用过这种表示法,没有不良副作用,也没有误解。这是有道理的——毕竟,字符串只是一个字符数组。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 2011-03-26
      • 2012-11-10
      • 2015-05-21
      • 2011-10-29
      • 1970-01-01
      相关资源
      最近更新 更多