Usando una matriz como agujas en strpos


91

¿Cómo se usa strpospara una serie de agujas cuando se busca una cadena? Por ejemplo:

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpos($string, $find_letters) !== false)
{
    echo 'All the letters are found in the string!';
}

Porque al usar esto, no funcionaría, sería bueno si hubiera algo como esto

Respuestas:


138

@Guarde un fragmento actualizado de http://www.php.net/manual/en/function.strpos.php#107351

function strposa($haystack, $needles=array(), $offset=0) {
        $chr = array();
        foreach($needles as $needle) {
                $res = strpos($haystack, $needle, $offset);
                if ($res !== false) $chr[$needle] = $res;
        }
        if(empty($chr)) return false;
        return min($chr);
}

Cómo utilizar:

$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');

if (strposa($string, $array, 1)) {
    echo 'true';
} else {
    echo 'false';
}

volverá true, debido a array "cheese".

Actualización: código mejorado con parada cuando se encuentra la primera de las agujas:

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
        if(strpos($haystack, $query, $offset) !== false) return true; // stop on first true result
    }
    return false;
}
$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');
var_dump(strposa($string, $array)); // will return true, since "cheese" has been found

1
@Arnaud, ¿cuál es su implemento sugerido?
Binyamin

5
No estoy seguro, pero tal vez podríamos avanzar en la cadena desde $ offset y detenernos cuando se encuentre la primera de las agujas. Piense en un texto grande lleno de "a". Tome $ agujas = [a, b]. Su función strposarecorrerá todo el texto, ¡pero no es necesario! ¿Soy comprensible?
Arnaud

¡Gracias @Arnaud por la sugerencia de función! Estoy totalmente de acuerdo con la importancia de su sugerencia y he actualizado mi respuesta con un ejemplo de código mejorado.
Binyamin

Esto no es exactamente lo que quería decir, porque con su nueva función $ needles = [b, a] todavía tiene un problema y, además, la función ya no devuelve la posición de la primera aparición. Déjame explicarte un poco más. Suponga que la cuerda es "ABCDEF", y las agujas son C y F. Lo que podríamos hacer es pasar por la cuerda: A, B ... C! Detectamos C, así que nos detenemos aquí y podemos devolver la posición de la primera aparición de una aguja, que es 2. Podría funcionar con más de cadenas de un solo carácter, pero no he pensado en la implementación exacta.
Arnaud

1
Mejoré el código cambiando foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, por lo que devuelve la clave del elemento coincidente para su posterior manejo.
James Cameron

54

str_replace es considerablemente más rápido.

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
$match = (str_replace($find_letters, '', $string) != $string);

error de sintaxis: 1 corchete de cierre demasiado en la línea # 3 (no pude corregirlo directamente en el código anterior debido al requisito de edición de> 6 caracteres;))
richey

1
Vaya, eso fue improvisado. Arreglado ahora. ¡Salud por el heads up!
León

8
una de las mejores soluciones!
andys

18

El siguiente código no solo muestra cómo hacerlo, sino que también lo pone en una función fácil de usar en el futuro. Fue escrito por "jesda". (Lo encontré en línea)

Código PHP:

<?php
/* strpos that takes an array of values to match against a string
 * note the stupid argument order (to match strpos)
 */
function strpos_arr($haystack, $needle) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $what) {
        if(($pos = strpos($haystack, $what))!==false) return $pos;
    }
    return false;
}
?>

Uso:

$needle = array('something','nothing');
$haystack = "This is something";
echo strpos_arr($haystack, $needle); // Will echo True

$haystack = "This isn't anything";
echo strpos_arr($haystack, $needle); // Will echo False 

Creo que esto solo devuelve la primera posición que encuentra. ¿Alguna sugerencia sobre cómo modificarlo para devolver la posición de cada aguja en el pajar?
Chaya Cooper

7

Puede iterar a través de la matriz y establecer un valor de "bandera" si strposdevuelve false.

$flag = false;
foreach ($find_letters as $letter)
{
    if (strpos($string, $letter) === false)
    {
        $flag = true;
    }
}

Luego verifique el valor de $flag.


6
¿No debería ser !== flase?
Joe Huang

¡Debería ser! == falso. A menos que se rompa justo después de poner su bandera en verdadero. Y luego tendría que interpretar la bandera como una advertencia de que no hay una aguja en el pajar. Eso significa que lo que estás intentando conseguir es comprobar que todas tus agujas están en el pajar. Cuál no es la cuestión. Así que sí. ! == falso
Kevin Gagnon

5

Si solo desea verificar si ciertos caracteres están realmente en la cadena o no, use strtok :

$string = 'abcdefg';
if (strtok($string, 'acd') === $string) {
    // not found
} else {
    // found
}

Respuesta increíble: ejecución MUCHO más rápida que múltiples strpos (), por ejemplo, if (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
The One and Only ChemistryBlob

5

La pregunta, ¿es el ejemplo proporcionado solo un "ejemplo" o exactamente lo que está buscando? Aquí hay muchas respuestas mixtas y no entiendo la complejidad de la aceptada.

Para averiguar si existe CUALQUIER contenido de la matriz de agujas en la cadena y devolver rápidamente verdadero o falso:

$string = 'abcdefg';

if(str_replace(array('a', 'c', 'd'), '', $string) != $string){
    echo 'at least one of the needles where found';
};

Si es así, dale a @Leon crédito a por eso.

Para averiguar si TODOS los valores de la matriz de agujas existe en la cadena, como en este caso, los tres 'a', 'b'y 'c'debe estar presente, al igual que usted menciona como su "por ejemplo"

echo '¡Todas las letras se encuentran en la cadena!';

Muchas respuestas aquí están fuera de ese contexto, pero dudo que la intención de la pregunta que marcó como resuelta. Por ejemplo, la respuesta aceptada es una aguja de

$array  = array('burger', 'melon', 'cheese', 'milk');

¿Y si todas esas palabras? DEBEN encontrarse en la cadena?

Entonces prueba algunos "not accepted answers"en esta página.


Esto funcionó perfectamente para mí, ya que estaba buscando que mi matriz contuviera subcadenas. Me salvé de escribir un comando sql como "% $ string%"
Maurice Elagu

4

Esta expresión busca todas las letras:

count(array_filter( 
    array_map("strpos", array_fill(0, count($letters), $str), $letters),
"is_int")) == count($letters)

3

Puedes probar esto:

function in_array_strpos($word, $array){

foreach($array as $a){

    if (strpos($word,$a) !== false) {
        return true;
    }
}

return false;
}

1

También puede intentar usar strpbrk () para la negación (no se ha encontrado ninguna de las letras):

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpbrk($string, implode($find_letters)) === false)
{
    echo 'None of these letters are found in the string!';
}

1

Este es mi enfoque. Repita los caracteres de la cadena hasta que encuentre una coincidencia. En una gama más grande de agujas, esto superará la respuesta aceptada porque no es necesario revisar todas las agujas para determinar que se ha encontrado una coincidencia.

function strpos_array($haystack, $needles = [], $offset = 0) {
    for ($i = $offset, $len = strlen($haystack); $i < $len; $i++){
        if (in_array($haystack[$i],$needles)) {
            return $i;
        }
    }
    return false;
}

Comparé esto con la respuesta aceptada y con una matriz de más de 7 $needlesesto fue dramáticamente más rápido.


0

Con el siguiente código:

$flag = true;
foreach($find_letters as $letter)
    if(false===strpos($string, $letter)) {
        $flag = false; 
        break;
    }

Luego verifique el valor de $flag. Si es así true, se han encontrado todas las letras. Si no, lo es false.


0

Estoy escribiendo una nueva respuesta que espero ayude a cualquiera que busque algo similar a lo que yo soy.

Esto funciona en el caso de "Tengo varias agujas y estoy tratando de usarlas para encontrar una cuerda individual". y esta es la pregunta que encontré para encontrar eso.

    $i = 0;
    $found = array();
    while ($i < count($needle)) {
        $x = 0;
        while ($x < count($haystack)) {
            if (strpos($haystack[$x], $needle[$i]) !== false) {
                array_push($found, $haystack[$x]);
            }
            $x++;
        }
        $i++;
    }

    $found = array_count_values($found);

La matriz $foundcontendrá una lista de todas las agujas coincidentes, el elemento de la matriz con el valor de recuento más alto será la cadena (s) que está buscando, puede obtener esto con:

print_r(array_search(max($found), $found));

0

Responde a @binyamin y @Timo .. (no hay suficientes puntos para agregar un comentario ..) pero el resultado no contiene la posición ..
El siguiente código devolverá la posición real del primer elemento, que es lo que strpos pretende hacer. Esto es útil si espera encontrar exactamente 1 coincidencia. Si espera encontrar múltiples coincidencias, entonces la posición del primero encontrado puede no tener sentido.

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
      $res=strpos($haystack, $query, $offset);
      if($res !== false) return $res; // stop on first true result
    }
    return false;
}

0

Solo una actualización de las respuestas anteriores

function strsearch($findme, $source){
    if(is_array($findme)){
        if(str_replace($findme, '', $source) != $source){
            return true;
        }
    }else{
        if(strpos($source,$findme)){
            return true;
        }
    }
    return false;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.