$ str [0]を使用して文字列の最初の文字を取得する


275

文字列の最初の文字を取得したいのですが、うまく機能していることに気づきました$str[0]。この表記法は一般的に配列で使用されるため、これが「良い習慣」であるかどうかはわかりません。この機能は十分に文書化されていないようですので、この表記を使用することが(すべての点で)大丈夫かどうかを教えてください。

それとも私は良いOLに固執するべきsubstr($str, 0, 1)ですか?

また、中かっこ($str{0})も機能することに注意してください。どうしたの?


5
プラス1 "good ol 'substr($ str、0、1)"。
サンティアゴ

回答:


388

はい。文字列は文字配列と見なすことができ、配列の位置にアクセスする方法は[]演算子を使用することです。通常、使用にまったく問題はありません$str[0](また、このsubstr()方法よりもはるかに高速であると確信しています)。

どちらの方法でも注意点は1つだけあります。つまり、最初の文字ではなく最初のバイトを取得します。マルチバイトエンコーディング(UTF-8など)を使用している場合、これは重要です。それをサポートしたい場合は、を使用してください。間違いなく、最近は常にマルチバイト入力を想定する必要があるため、これが最良のオプションですが、少し遅くなります。mb_substr()


7
PHPの$ str [0]では、2バイトの長い文字が存在する可能性があることを考慮していますか?UTFなど (substr()もそれを助けません!)
Tomer W

77
さらに安全にしたい場合はmb_substr($str, 0, 1, 'utf-8')、マルチバイト文字列を切り捨てないようにしてください。
Vic

18
これはに比べて短く、覚えやすいですがsubstr($str, 0, 1)、コードを読む人を混乱させます。
トランテ2013年

10
大括弧とsubstr()のどちらを選択するかは主に好みの問題ですが、空の文字列に適用した場合の結果は異なることに注意してください。$ s = ""の場合、$ s [] === ""ですが、substr($ s、0、1)=== falseです。
xtempore 2014

9
$ s = ""の場合、$ s [0]は "Notice:Uninitialized string offset:0"を生成しますが、substr($ s、0、1)は生成しません。
クリス、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

1
@MarcoDemaioこのリンクは、MichaelMortonの発言を伝えます。
ティノ

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 2018年

25

$ _POSTの一部の最初の文字だけが欲しいとしましょう、それを 'type'と呼びましょう。そして、その$ _POST ['type']は現在「Control」です。この場合には、あなたが使用している場合場合$_POST['type'][0]、またはsubstr($_POST['type'], 0, 1)あなたが取得しますCバック。

ただし、クライアント側が送信したデータtypetype[]、たとえばからに変更してから、この配列のデータとして「Control」と「Test」を送信した場合、単に失敗するのではなく、$_POST['type'][0]ここで戻ります。ControlCsubstr($_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
エラートファンコペレン

正確な測定を行うには、ループのマイクロタイムをより適切に実行し、同じループ内で異なるアプローチを混在させないでください。
PypeBros

1
実行ミキシングないtestAtestB例えばあなたが検出することができる同じループ手段内を実際testBのキャッシュ・キラー中であるが、testAキャッシュに優しいです。両方が同じループにある場合、testB汚染されたtestAのキャッシュのため、タイミングが非常に同じであると測定されます。
PypeBros

1
同様に、テストループ内で文字列やランダムを生成することは避け、近くの配列でそれらを準備します。
PypeBros

1
-1; 疑わしいタイミングメカニズムは別にしておきます(一度に1つずつ時間を計測するよりも、多くの操作を時間計測する方が良いでしょう。microtime()実験的にはそうではありますが、呼び出しにかかった時間だけがほとんどの時間差を占めてしまうことを心配しました。真実ではありません)、ここで小さな速度の違いを気にする理由はありません。100分の1秒のほんの一部です。これはいつ問題になるのですか?
Mark Amery 2017年

6

単なる人間といえば、私はこだわり$str[0]ます。私の知る限りで$str[0]は、一目でその意味を理解する方が簡単です。substr($str, 0, 1)。これはおそらく好みの問題に要約されます。

パフォーマンスに関する限り、プロファイルプロファイルプロファイル。:)または、PHPソースコードを覗き見ることができます...


6
$str = 'abcdef';
echo $str[0];                 // a

6
-1; OPの質問は、この構文が悪い習慣であるかどうかでした、そしてあなたは...何の解説もなく構文を繰り返すことによって応答しましたか?これは答えではありません。
Mark Amery 2017年


1

私は以前にもその表記法を使用しましたが、悪影響や誤解はありません。結局のところ、文字列は単なる文字の配列です。


いいえ、文字列は文字の配列ではありません(少なくともPHPが2つの用語を使用しているため)。-1。
Mark Amery 2017年


@gattsbrは内部的にはそうですが、PHPが公開するモデルに関する限り、根本的に異なるものです。角括弧表記を使用してオフセットにアクセスすることは、配列に共通する操作がほとんど唯一の操作です。文字列関数は配列では機能せず、その逆も同様です。また、配列の追加構文($arr[] = $new_element)は文字列では機能しません。そのため、文字配列を文字配列として考えることは有用ではないと思います。
Mark Amery 2017年

@markameryは、php.netのマニュアルを書き直して、そのような非常に微細な技術を組み込んだほうがよいでしょう。
gattsbr 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.