2011-01-05 17 views
69

¿Hay alguna forma de iterar sobre los caracteres de una cadena? Me gustaría poder hacer foreach, array_map, array_walk, array_filter etc. en los caracteres de una cadena.PHP: iterar en los caracteres de cadena

El tipo de fundición/malabarismo no me llevó a ninguna parte (puse toda la cadena como un elemento de la matriz), y la mejor solución que he encontrado es simplemente usar un ciclo for para construir la matriz. Se siente como si hubiera algo mejor. Quiero decir, si puedes indexar, ¿no deberías poder iterar también?

Este es el mejor que tengo

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); 

¿Hay ya sea:

A) Una manera de hacer que la cadena iterables
B) Una mejor manera de construir la matriz de caracteres de la cadena (y si es así, ¿qué tal la otra dirección?)

Siento que me falta algo obvio aquí.

+0

tal vez debería decir más de que estamos tratando de lograr ... parece que puede haber una mejor manera de hacerlo utilizando las operaciones normales de cadena. –

+0

no tiene un objetivo real aquí. solo una curiosidad con la que estaba jugando. Parecía extraño que, aunque puedes indexar cadenas, no puedes iterar. No podía ni siquiera pensar en ejemplos de uso significativos, pero aún me gustaría saber si hay alguna manera de iterar en los caracteres de cadenas sin construir una matriz de caracteres explícitamente –

+0

, pero es un buen punto, obviamente mis ejemplos son bastante superficiales. es decir, casi todo lo que harías con 'array_filter' en este sentido se podría hacer mejor con las funciones de cadena o reg-ex –

Respuesta

89

Paso 1: convertir la cadena en una matriz mediante la función str_split

$array = str_split($your_string);

Paso 2: bucle a través de la matriz recién creado

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

Puede comprobar el Documentos de PHP para más información: str_split

+0

hah wow. sí, eso es todo. y por supuesto implode puede hacer la otra dirección. Aceptaré esto pronto a menos que alguien pueda mostrar una forma de hacer la iteración directamente en el aguijón –

+0

@jon_darkstar No conozco su aplicación, pero tenga en cuenta que cada entrada en una matriz tiene una sobrecarga significativa (4bytes IIRC). Omita eso, es 'bastante' mucho más: http://nikic.github.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html –

19

Si las cuerdas están en Unicode se debe utilizar con preg_split/u modificador

De los comentarios de la documentación de 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

Para cadenas multibyte, ' mb_split' es más confiable. – Xenon

5

Ampliado de @SeaBrightSystems respuesta, usted podría intentar esto:

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

Downvoted porque esta respuesta no agrega ningún valor. @SeaBrightSystems respuesta ya contiene toda la información necesaria y un enlace a la documentación. –

+0

No estoy de acuerdo, esta respuesta sí agrega valor, brinda un ejemplo práctico de cómo str_split podría funcionar en una aplicación PHP. @SeaBrightSystems simplemente vincula a la documentación, que a veces no es tan útil cuando una persona intenta ver cómo funciona una función, dado un ejemplo. De lo contrario, la mayoría de las respuestas de SO serían solo enlaces a php.net – kurdtpage

+0

@kurdtpage La documentación de php es una de las mejores documentaciones que conozco. Hay muchos ejemplos muy buenos para cada función y los ejemplos para 'str_split' son mucho más detallados que su ejemplo. –

6

También puede acceder a $ s1 como una matriz, si solo necesita acceder a ella:

$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

Para aquellos que buscan la forma más rápida de iterar sobre cadenas en php, he preparado una prueba comparativa.
El primer método en el que se accede directamente caracteres de cadena especificando su posición en los soportes y el tratamiento de cadena como una matriz:

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

yo mismo pensaba que el último es el método más rápido, pero estaba equivocado.
Como con el segundo método (que se utiliza en la respuesta aceptada):

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

Este método va a ser más rápido causa que estamos utilizando una matriz verdadero y no asumir que uno sea una matriz.

Llamar a la última línea de cada uno de los métodos anteriores para 1000000 veces conducen a estos resultados de evaluación comparativa:

El uso de cuerdas [i]
0.24960017204285 Seconds

Usando str_split
0.18720006942749 Seconds

Lo que significa que el segundo método es mucho más rápido.

25

cadena Iterar:

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

Parece una mejor respuesta porque responde a la pregunta, es decir, cómo iterar sobre una cadena en lugar de 'convertir a matriz'. – Robin

Cuestiones relacionadas