PHP-文字列文字に対して反復


120

文字列の文字を反復する良い方法はありますか?私が行うことができるようにしたいのですがforeacharray_maparray_walkarray_filterなどの文字列の文字に。

タイプキャスティング/ジャグリングではどこにも行かず(文字列全体を配列の1つの要素として出力します)、私が見つけた最良の解決策は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 2011

1
ここには本当の目的はありません。私が遊んでいた好奇心。文字列にインデックスを付けることができても、反復できないことは奇妙に思えました。意味のある例の使用法を考えるのに途方に暮れていましたが、文字配列を明示的に構築せずに文字列の文字を反復処理する方法があるかどうか知りたいのですが
jon_darkstar

それは良い点ですが、明らかに私の例はかなり浅いです。つまりarray_filter、この意味で行うほとんどすべてのことは、文字列またはreg-ex関数でより適切に実行できる
jon_darkstar

projecteuler.net/problem=20の解決は、(多少は工夫されていますが)ユースケースの例です。
Nick Edwards

for($ i = 0; $ i <strlen($ s); $ i ++)に関しては、ループする前にstrlen($ s)を変数に格納することに注意してください。このようにして、strlen()を呼び出します。 1回
2017

回答:


176

手順1:str_split関数を使用して文字列を配列に変換する

$array = str_split($your_string);

ステップ2:新しく作成したアレイをループする

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

詳細については、PHPのドキュメントを確認してください。 str_split


うわぁ。うんそれだ。もちろん、内破は別の方向を向くことができます。誰かがスティングで正しくイテレーションを行う方法を示さない限り、すぐにこれを受け入れます
jon_darkstar

@jon_darkstarあなたのアプリケーションはわかりませんが、配列の各エントリにはかなりのオーバーヘッド(4バイトIIRC)があることに注意してください。それをスキップすることで、より「かなり」方法です:nikic.github.com/2011/12/12/...
大安Timmer

str_split() will split into bytes, rather than characters when dealing with a multi-byte encoded string.-そうはstr_splitユニコードで作業することはできません
ハッピー

85

文字列を繰り返す:

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

7
これは、「配列に変換する」ではなく、文字列を反復する方法という質問に答えるため、より良い答えのようです。
ロビンアンドリュース

2
笑!!!!!@OmarTariqすべて。これは、提供された回答よりもはるかに効率的です。
0x476f72616e 2018年

5
strlen()繰り返しごとに呼び出すことに注意してください。PHPの長さは事前に計算されているため、ひどいことではありませんが、それでも関数呼び出しです。速度が必要な場合は、ループを開始する前に変数に保存することをお勧めします。
Vilx-

2
これはマルチバイト文字列には適していません。これは、シンボルではなくバイトオフセットを
取得し

2
@OmarTariq 「これが答えです。世界の何が悪いのですか?」....世界の悪い点は、世界に英語以外の言語があることです。この関数は、いつものように、文字ではなく文字列のバイトを反復します。
会計士م

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より信頼性があります。
エレクトラ2017

12

$ s1にアクセスするだけでよい場合は、配列のようにアクセスすることもできます。

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

6

@SeaBrightSystemsの回答から拡張して、これを試すことができます。

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

私は同意しません。この答えは価値を追加します。それは、PHPアプリケーションでstr_splitがどのように機能するかを示す実例です。@SeaBrightSystemsはドキュメントへのリンクにすぎません。例を挙げれば、関数がどのように機能するかを確認しようとしているときに、あまり役に立たないことがあります。そうでなければ、ほとんどのSOの回答はphp.netへのリンクになります
kurdtpage

6

PHPで文字列を反復処理する最速の方法を探している人のために、ベンチマークテストを用意しました。
角かっこで位置を指定し、文字列を配列のように扱うことによって文字列文字に直接アクセスする最初の方法:

$string = "a sample string for testing";
$char = $string[4] // equals to m

私自身は後者が最も速い方法だと思いましたが、私は間違っていました。
2番目の方法(受け入れられた回答で使用される)と同様:

$string = "a sample string for testing";
$string = str_split($string);
$char = $string[4] // equals to m

この方法は、実際の配列を使用していて、配列であるとは想定していないため、より高速になります。

上記の各メソッドの最後の行を1000000何度も呼び出すと、次のベンチマーク結果が得られます。

string [i]の使用
0.24960017204285 Seconds

str_splitの使用
0.18720006942749 Seconds

つまり、2番目の方法の方がはるかに高速です。


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文字ではなくBYTESをカウントします。そのため、その兄弟関数は英語の文字で正常に機能します。英語の文字は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) "ث"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.