2011-01-05 3 views
69

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

Тип 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); 

Есть ли либо:

А) способ сделать строку итерации
B) лучшим способом для создания массива символов из строка (и если да, то как насчет другого направления?)

Я чувствую, что у меня что-то явно не видно.

+0

Может быть, вы должны говорить больше о том, что вы пытаетесь сделать ... похоже, что может быть лучше сделать это с помощью обычных операций над строками. –

+0

здесь нет настоящей цели. просто любопытство, с которым я играл. казалось странным, что даже если вы можете индексировать строки, которые вы не можете повторить. я был в недоумении даже придумывать осмысленный пример использования, но мне все же хотелось бы знать, есть ли какой-то способ итерации на строковых символах без конструирования массива символов explictly –

+0

, что хорошо, хотя, очевидно, мои примеры довольно мелкие. т.е. в большинстве случаев все, что вы делали бы с 'array_filter' в этом смысле, могло бы быть лучше сделано с помощью строковых или рег-ex-функций. –

ответ

89

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

$array = str_split($your_string);

Шаг 2: цикл через вновь созданный массив

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

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

+0

hah wow. Да, это так. и, конечно же, развязать может сделать другое направление. Я скоро приму это, если кто-то не сможет показать способ сделать итерацию прямо на жало –

+0

@jon_darkstar Я не знаю вашего приложения, но обратите внимание, что каждая запись в массиве имеет значительные накладные расходы (4 байта IIRC). Пропустите это, это «совершенно» путь больше: http://nikic.github.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html –

19

Если ваши строки в 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); 
} 
+0

Для многобайтовых строк ' mb_split' является более надежным. – Xenon

5

Expanded от @SeaBrightSystems ответа, вы можете попробовать это:

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

Downvoted, потому что этот ответ не добавляет значения. Ответ @SeaBrightSystems уже содержит всю необходимую информацию и ссылку на документацию. –

+0

Я не согласен, этот ответ добавляет ценность, он дает рабочий пример того, как str_split может работать в приложении PHP. @SeaBrightSystems просто ссылается на документацию, что иногда не так полезно, когда человек пытается увидеть, как функция может работать, на примере. В противном случае большинство ответов SO были бы просто ссылками на php.net. – kurdtpage

+0

@kurdtpage. Документация php - одна из лучших документов, которые я знаю. Для каждой функции есть несколько очень хороших примеров, а примеры для 'str_split' являются более подробными, чем его пример. –

6

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

$s1 = "hello world"; 
echo $s1[0]; // -> h 
0
// 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

Для тех, кто ищет самый быстрый способ перебора строк в 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 

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

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

Использование String [I]
0.24960017204285 Seconds

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

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

25

Iterate строка:

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

Это похоже на лучший ответ, потому что он отвечает на вопрос - например, как перебирать строку, а не «преобразовывать в массив». – Robin

Смежные вопросы