web-dev-qa-db-ja.com

PHP-文字列文字で反復

文字列の文字を繰り返す良い方法はありますか?文字列の文字に対して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)文字列から文字配列を作成するより良い方法(もしそうなら、他の方向はどうですか?)

ここで明らかな何かを見逃しているような気がします。

101
jon_darkstar

ステップ1:str_split関数を使用して文字列を配列に変換します

$array = str_split($your_string);

ステップ2:新しく作成された配列をループします

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

詳細については、PHPのドキュメントを確認できます。 str_split

144

文字列の反復:

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

文字列が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 ); 
} 
19
Dawid Ohia

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

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

@SeaBrightSystemsの回答から展開して、これを試すことができます:

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

PHPで文字列を反復処理する最速の方法を探している人のために、Iveはベンチマークテストを準備しました。
ブラケット内の位置を指定し、文字列を配列のように扱うことにより、文字列の文字に直接アクセスする最初の方法:

$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

このメソッドは、real配列を使用し、配列であると想定しないため、より高速になります。

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

string [i]を使用
0.24960017204285 Seconds

str_splitの使用
0.18720006942749 Seconds

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

5
AmirHossein

うーん...物事を複雑にする必要はありません。基本は常にうまく機能します。

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

順方向:

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

出力:abcdef

逆方向:

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

出力:fedcba

3
Ash
// 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;
}
2
masakielastic

回答のほとんどは、英語以外の文字を忘れていました!!!

strlenは文字ではなくBYTESをカウントするので、英語の文字はUTF-8とASCIIエンコードの両方で1バイトに格納されるため、兄弟関数は英語の文字で問題なく動作します。 マルチバイト文字列関数mb_*を使用する必要があります

これは、UTF-8でエンコードされたany文字で動作します

$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) "ث"
0
Accountant م