PHP - перебирать строковые символы - PullRequest
96 голосов
/ 05 января 2011

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

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

Я чувствую, что яздесь чего-то не хватает.

Ответы [ 8 ]

141 голосов
/ 05 января 2011

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

$array = str_split($your_string);

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

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

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

58 голосов
/ 24 октября 2016

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

for ($i = 0; $i < strlen($str); $i++){
    echo $str[$i];
}
19 голосов
/ 08 января 2012

Если ваши строки в 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 ); 
} 
8 голосов
/ 19 февраля 2016

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

$s1 = "hello world";
echo $s1[0]; // -> h
5 голосов
/ 02 сентября 2016

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

$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

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

5 голосов
/ 15 мая 2015

Расширено из ответа @SeaBrightSystems, вы можете попробовать это:

$s1 = "textasstringwoohoo";
$arr = str_split($s1); //$arr now has character array
2 голосов
/ 21 декабря 2018

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

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

Направление вперед:

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

Выходы: abcdef

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

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

Выходы: fedcba

0 голосов
/ 29 августа 2016
// 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;
}
...