Fonction in_array insensible à la casse PHP

131

Est-il possible de faire une comparaison insensible à la casse lors de l'utilisation de la in_arrayfonction?

Donc, avec un tableau source comme celui-ci:

$a= array(
 'one',
 'two',
 'three',
 'four'
);

Les recherches suivantes renverraient toutes true:

in_array('one', $a);
in_array('two', $a);
in_array('ONE', $a);
in_array('fOUr', $a);

Quelle fonction ou quel ensemble de fonctions ferait de même? Je ne pense pas qu'elle in_arraypuisse faire ça.

leepowers
la source

Réponses:

101

vous pouvez utiliser preg_grep():

$a= array(
 'one',
 'two',
 'three',
 'four'
);

print_r( preg_grep( "/ONe/i" , $a ) );
ghostdog74
la source
37
utiliser des expressions régulières n'est pas une bonne solution, car cela peut être lent ... peut-être que array_map est plus rapide
phil-opp
5
Pour en faire une solution de remplacement pour in_array, un retour bool, il devient: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Pas si élégant, alors. (Notez que les caractères ^ et $ sont obligatoires, sauf si une correspondance partielle est souhaitée.) Cependant, si vous voulez réellement que les entrées correspondantes soient renvoyées, j'aime cette solution.
Darren Cook le
2
Le dernier commentaire contient une erreur de syntaxe: / $ devrait être $ / à la place.
Gogowitsch
1
@DarrenCook pour autant que je sache, un cast booléen fonctionnerait également (bool) preg_grep ('/ ^'. Preg_quote ($ aiguille). '$ /', $ A), comme un tableau vide serait
converti
8
On dirait que le moyen le plus simple est de simplement convertir en minuscules.
Joshua Dance
229

La chose évidente à faire est simplement de convertir le terme de recherche en minuscules:

if (in_array(strtolower($word), $array)) { 
  ...

bien sûr, s'il y a des lettres majuscules dans le tableau, vous devrez d'abord le faire:

$search_array = array_map('strtolower', $array);

et recherchez cela. Il ne sert à rien de faire strtolowersur l'ensemble du tableau à chaque recherche.

La recherche de tableaux est cependant linéaire. Si vous avez un grand tableau ou que vous comptez faire beaucoup cela, il serait préférable de mettre les termes de recherche dans la clé du tableau car ce sera un accès beaucoup plus rapide:

$search_array = array_combine(array_map('strtolower', $a), $a);

puis

if ($search_array[strtolower($word)]) { 
  ...

Le seul problème ici est que les clés de tableau doivent être uniques, donc si vous avez une collision (par exemple "One" et "one"), vous en perdrez toutes sauf une.

cletus
la source
23
Cela devrait être la réponse acceptée. L'ajout d'expressions régulières pose parfois juste 2 problèmes.
Joshua Dance
1
Array_flip ne serait-il pas ici une solution encore plus rapide, au lieu de array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo
une ligne: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew
1
@Akira Yamamoto - Qu'y a-t-il avec la modification de la "syntaxe de correction" ? Nous ne sommes pas autorisés à corriger le code ici. Je l'ai fait reculer.
Funk Forty Niner
Ou utilisez array_change_key_case () secure.php.net/manual/en/function.array-change-key-case.php
boctulus
113
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

De la documentation

Tyler Carter
la source
3
Vous devriez bloquer le code (ou tout ce qui est vraiment) que vous obtenez d'ailleurs.
cletus
3
Juste pour être clair. Ce n'est pas une critique. Juste une suggestion (et seulement mon avis, rien d'officiel). :) Au moins si je copie un extrait de code d'une page, je bloquerai le citer.
cletus
3
De plus, l'utilisation d'un bloc de code le décrit mieux, car il s'agit de «code». Bloquer la citation ne lui permet pas d'être correctement formatée.
Tyler Carter
Je reste corrigé, après avoir utilisé le bouton réel pour ajouter >à chaque ligne, cela fonctionne. Je suis juste habitué à mettre manuellement le >en première ligne.
Tyler Carter
J'ai l'habitude d'utiliser ctrl-Q pour le faire. Cela pose un problème avec les blocs de code car, pour une raison quelconque, il encapsule les lignes. Ne me demandez pas pourquoi. Mais vous pouvez simplement corriger cela ou mettre manuellement un >au début de chaque ligne.
cletus
50
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Source: page de manuel de php.net in_array.

Gazler
la source
Si vous savez ce que contient le tableau, vous pouvez omettre array_map; mais c'est un bon exemple.
Don
2
Je l'ai fait en fait. Parce que mapper le tableau à chaque appel est, eh bien, ridicule.
cletus
De plus, en supposant (comme Chacha) que cela vient directement de la documentation, il est préférable de bloquer les citations.
cletus
10

Supposons que vous souhaitiez utiliser in_array, voici comment rendre la recherche insensible à la casse.

Insensible à la casse in_array ():

foreach($searchKey as $key => $subkey) {

     if (in_array(strtolower($subkey), array_map("strtolower", $subarray)))
     {
        echo "found";
     }

}

Normalement sensible à la casse:

foreach($searchKey as $key => $subkey) {

if (in_array("$subkey", $subarray))

     {
        echo "found";
     }

}
Mike Q
la source
2

Ce qui précède est correct si nous supposons que les tableaux ne peuvent contenir que des chaînes, mais que les tableaux peuvent également contenir d'autres tableaux. La fonction in_array () peut également accepter un tableau pour $ aiguille, donc strtolower ($ aiguille) ne fonctionnera pas si $ aiguille est un tableau et array_map ('strtolower', $ haystack) ne fonctionnera pas si $ haystack contient d'autres tableaux, mais entraînera un "avertissement PHP: strtolower () s'attend à ce que le paramètre 1 soit une chaîne, tableau donné".

Exemple:

$needle = array('p', 'H');
$haystack = array(array('p', 'H'), 'U');

J'ai donc créé une classe d'assistance avec les méthodes pertinentes, pour faire des vérifications in_array () sensibles à la casse et insensibles à la casse. J'utilise également mb_strtolower () au lieu de strtolower (), donc d'autres encodages peuvent être utilisés. Voici le code:

class StringHelper {

public static function toLower($string, $encoding = 'UTF-8')
{
    return mb_strtolower($string, $encoding);
}

/**
 * Digs into all levels of an array and converts all string values to lowercase
 */
public static function arrayToLower($array)
{
    foreach ($array as &$value) {
        switch (true) {
            case is_string($value):
                $value = self::toLower($value);
                break;
            case is_array($value):
                $value = self::arrayToLower($value);
                break;
        }
    }
    return $array;
}

/**
 * Works like the built-in PHP in_array() function — Checks if a value exists in an array, but
 * gives the option to choose how the comparison is done - case-sensitive or case-insensitive
 */
public static function inArray($needle, $haystack, $case = 'case-sensitive', $strict = false)
{
    switch ($case) {
        default:
        case 'case-sensitive':
        case 'cs':
            return in_array($needle, $haystack, $strict);
            break;
        case 'case-insensitive':
        case 'ci':
            if (is_array($needle)) {
                return in_array(self::arrayToLower($needle), self::arrayToLower($haystack), $strict);
            } else {
                return in_array(self::toLower($needle), self::arrayToLower($haystack), $strict);
            }
            break;
    }
}
}
Alex
la source
1

J'ai écrit une fonction simple pour vérifier une valeur insensible dans un tableau dont le code est ci-dessous.

fonction:

function in_array_insensitive($needle, $haystack) {
   $needle = strtolower($needle);
   foreach($haystack as $k => $v) {
      $haystack[$k] = strtolower($v);
   }
   return in_array($needle, $haystack);
}

comment utiliser:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));
Jake
la source
1
/**
 * in_array function variant that performs case-insensitive comparison when needle is a string.
 *
 * @param mixed $needle
 * @param array $haystack
 * @param bool $strict
 *
 * @return bool
 */
function in_arrayi($needle, array $haystack, bool $strict = false): bool
{

    if (is_string($needle)) {

        $needle = strtolower($needle);

        foreach ($haystack as $value) {

            if (is_string($value)) {
                if (strtolower($value) === $needle) {
                    return true;
                }
            }

        }

        return false;

    }

    return in_array($needle, $haystack, $strict);

}


/**
 * in_array function variant that performs case-insensitive comparison when needle is a string.
 * Multibyte version.
 *
 * @param mixed $needle
 * @param array $haystack
 * @param bool $strict
 * @param string|null $encoding
 *
 * @return bool
 */
function mb_in_arrayi($needle, array $haystack, bool $strict = false, ?string $encoding = null): bool
{

    if (null === $encoding) {
        $encoding = mb_internal_encoding();
    }

    if (is_string($needle)) {

        $needle = mb_strtolower($needle, $encoding);

        foreach ($haystack as $value) {

            if (is_string($value)) {
                if (mb_strtolower($value, $encoding) === $needle) {
                    return true;
                }
            }

        }

        return false;

    }

    return in_array($needle, $haystack, $strict);

}
Carlos Coelho
la source
Finalement. Il a fallu 8 ans avant que quelqu'un intervienne et fournisse la technique la plus efficace - un débutreturn . Lorsqu'il suffit de trouver 1 aiguille, il est inutile de continuer à itérer après l'avoir trouvée. Je corrigerais une faute de frappe, utiliserais le concept $ strict et apporterais quelques améliorations, peut-être quelque chose de proche de 3v4l.org/WCTi2 . Ce message n'est pas parfait, mais son cœur est au bon endroit.
mickmackusa
0
$a = [1 => 'funny', 3 => 'meshgaat', 15 => 'obi', 2 => 'OMER'];  

$b = 'omer';

function checkArr($x,$array)
{
    $arr = array_values($array);
    $arrlength = count($arr);
    $z = strtolower($x);

    for ($i = 0; $i < $arrlength; $i++) {
        if ($z == strtolower($arr[$i])) {
            echo "yes";
        }  
    } 
};

checkArr($b, $a);
omer
la source
1
Veuillez ajouter une description de la solution que vous proposez.
il_raffa
-2
  • in_array accepte ces paramètres: in_array (recherche, tableau, type)
  • si le paramètre de recherche est une chaîne et que le paramètre de type est défini sur TRUE, la recherche est sensible à la casse.
  • donc pour que la recherche ignore la casse, il suffirait de l'utiliser comme ceci:

$ a = tableau ('un', 'deux', 'trois', 'quatre');

$ b = in_array ('ONE', $ a, faux);

utilisateur1077915
la source
6
Le troisième paramètre contrôle si le type de la variable est vérifié ou non, pas la casse . Quand truedes comparaisons de type strictes seront utilisées, par exemple '1' !== 1. Lorsque la falsejonglerie de type sera utilisée, par exemple '1' == 1. Voir php.net/in_array et php.net/manual/en/types.comparisons.php pour la documentation.
leepowers