使用$ str [0]获取字符串的第一个字符


275

我想获取字符串的第一个字母,并且我注意到它的$str[0]效果很好。我只是不确定这是否是“好的做法”,因为该符号通常用于数组。这个功能似乎没有得到很好的记录,因此我想请大家告诉我在所有方面都可以使用此符号吗?

还是我应该坚持好礼substr($str, 0, 1)

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


5
对于“ good ol'substr($ str,0,1)”加1。
圣地亚哥

Answers:


389

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

两种方法都只有一个警告:它们将获得第一个字节,而不是第一个字符。如果您使用多字节编码(例如UTF-8),则这一点很重要。如果您要支持该功能,请使用mb_substr()。可以争论的是,这些天您应该始终假设使用多字节输入,因此这是最好的选择,但是会稍慢一些。


7
PHP $ str [0]是否考虑到可以有2Byte长字符?UTF之类的?(即使substr()也无济于事!)
Tomer W

77
如果您想超级安全,就应该选择mb_substr($str, 0, 1, 'utf-8')这样做,以免截断多字节字符串。
维克

18
尽管它比的要短并且易于记忆substr($str, 0, 1),但是这会使读取代码的人感到困惑。
trante

10
方括号和substr()之间的选择在很大程度上取决于首选项,但是请注意,将其应用于空字符串时,结果是不同的。如果$ s =“”,则$ s [] ===“”,但substr($ s,0,1)===否。
xtempore 2014年

9
如果$ s =“”,则$ s [0]将生成一个“ Notice:Uninitialized string offset:0”,而substr($ s,0,1)不会。
克里斯(Chris)2014年

46

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


14
docs.php.net/language.types.stringNote: 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

4
@VolkerK:在您提供的链接上,我注意到他们删除了仅留在他们的PHP手册上的注释:Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.因此,我想知道他们是否决定{}从PHP 6起不再弃用
Marco Demaio,2012年

1
@MarcoDemaio现在,该链接说明了MichaelMorton所说的内容。
2014年

1
“没有给出弃用的指示” -事实上,过时消息,已经在修订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/...
VolkerK

截止到今天(18年5月10日),引用过的PHP文档的报价是: Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose. 似乎这种语法将保留一段时间。
Fr0zenFyr

25

假设您只希望$ _POST的一部分中的第一个字符,将其称为“类型”。$ _POST ['type']当前为“控件”。如果在这种情况下使用$_POST['type'][0]substr($_POST['type'], 0, 1)则将C返回。

但是,如果客户端被修改他们给你,从数据typetype[]例如,然后发送“控制”和“测试”作为此数组中的数据,$_POST['type'][0]现在将返回Control,而不是C,而substr($_POST['type'], 0, 1)将只是简单地失败。

所以是的,使用可能存在问题$str[0],但这取决于周围的环境。


2
作为避免这一特殊问题的附带说明,无论哪种情况,都应始终执行数据验证。if (true === is_string($_POST['type']))
fyrye

13

我唯一的疑问是该技术在多字节字符串上的适用性,但是如果不考虑这一点,那么我怀疑您已被覆盖。(如果有疑问,mb_substr()显然是一个安全的选择。)

但是,从全局的角度来看,我想知道您需要多长时间访问一次字符串中的第n个字符才能将此作为关键考虑因素。


9

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

<?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

似乎使用[]or {}运算符大致相同。


2
不错的测试!来自3岁Xeon的一些数字:使用“ array []”的平均浮动时间为2.2427082061768E-7,使用“ substr()”的平均浮动时间为3.9647579193115E-7使用“ array {}”的平均浮动时间为2.1522283554077E-7
Ellert van Koperen

为了获得准确的测量结果,您最好不要在循环中进行微时间操作,并且不要在同一循环中混用不同的方法。
PypeBros '16

1
未混合的执行testAtestB相同的循环意味着你能够检测例如在事实中testB是一个高速缓存,而凶手testA是缓存友好。当它们都处于同一循环中时,由于testB污染testA的缓存,它们被测量为具有相同的时序。
PypeBros

1
同样,我会避免在测试循环中生成字符串或随机数,并将它们准备在附近的阵列中。
PypeBros

1
-1; 抛开有问题的计时机制(对许多操作计时比一次计时更好;我担心阅读此信息,只是进行microtime()通话所花费的时间会弥补大部分时差,尽管从实验上看,这似乎(不是真的),这里没有理由关心微小的速度差异。不到一秒的百万分之一;这什么时候重要?
Mark Amery

6

我只是凡人,我会坚持下去$str[0]。就我而言,$str[0]一目了然比更快地了解的含义substr($str, 0, 1)。这可能归结为偏好问题。

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




1

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


不,字符串不是字符数组(至少因为PHP使用这两个术语)。-1。
Mark Amery


@gattsbr在内部是,但是就PHP公开的模型而言,它们是根本不同的东西。使用方括号表示法访问偏移量几乎是它们与数组共同的唯一操作。字符串函数不适用于数组,反之亦然,数组附加语法($arr[] = $new_element)不适用于字符串。因此,我认为将字符串理解为字符数组是没有用的。
Mark Amery

@markamery最好改写php.net手册,然后再包含这么小的技巧。
gattsbr
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.