Подтвердить что ты не робот

PHP - итерация по строковым символам

Есть ли хороший способ перебора символов строки? Я хотел бы иметь возможность делать foreach, array_map, array_walk, array_filter и т.д. Для символов строки.

Тип casting/juggling не получил меня нигде (поместите всю строку как один элемент массива), и лучшее решение, которое я нашел, просто использует цикл 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) Лучший способ построить массив символов из строки (и если да, то как насчет другого направления?)

Мне кажется, что у меня что-то не так очевидно.

4b9b3361

Ответ 1

Шаг 1: преобразовать строку в массив с str_split функции str_split

$array = str_split($your_string);

Шаг 2: цикл по вновь созданному массиву

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

Вы можете проверить PHP документацию для получения дополнительной информации: str_split

Ответ 2

Итерация строки:

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

Ответ 3

Если ваши строки находятся в Юникоде, вы должны использовать 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 ); 
} 

Ответ 4

Вы также можете просто получить доступ к $s1 как массив, если вам нужно только получить к нему доступ:

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

Ответ 5

Развернутый из @SeaBrightSystems ответ, вы можете попробовать следующее:

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

Ответ 6

Для тех, кто ищет быстрый способ перебора строк в php, Ive подготовил тестовое тестирование.
Первый метод, в котором вы напрямую обращаетесь к строковым символам, указав его положение в скобках и обрабатывая строку как массив:

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

Я сам думал, что последний является самым быстрым методом, но я ошибся.
Как и во втором методе (который используется в принятом ответе):

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

Этот метод будет более быстрым, потому что мы используем массив real и не предполагаем, что он является массивом.

Вызов последней строки каждого из приведенных выше методов для 1000000 раз приводит к этим результатам бенчмаркинга:

Использование строки [i]
0.24960017204285 Seconds

Использование str_split
0.18720006942749 Seconds

Это означает, что второй метод работает быстрее.

Ответ 7

Хм... Нет необходимости усложнять вещи. Основы работают отлично всегда.

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

Прямое направление:

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

Выходы: abcdef

Обратное направление:

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

Выходы: fedcba

Ответ 8

// 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;
}

Ответ 9

Большинство ответов забыли о неанглийских символах !!!

strlen считает бАЙТЫ, а не символы, поэтому он и его родственные функции отлично работают с английскими символами, поскольку английские символы хранятся в 1 байте в кодировках UTF-8 и ASCII, вам необходимо использовать многобайтовый код строковые функции 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) "ث"