PHP in_array insensibile alle maiuscole / minuscole


131

È possibile effettuare un confronto senza distinzione tra maiuscole e minuscole quando si utilizza la in_arrayfunzione?

Quindi con un array di origine come questo:

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

Le seguenti ricerche restituiranno tutte vere:

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

Quale funzione o insieme di funzioni farebbe lo stesso? Non penso che in_arraypossa farlo da solo.

Risposte:


101

puoi usare preg_grep():

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

print_r( preg_grep( "/ONe/i" , $a ) );

37
usare le espressioni regolari non è una buona soluzione, perché può essere lento ... forse array_map è più veloce
phil-opp,

5
Per rendere un rimpiazzo per in_array, restituendo un bool, diventa: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Non così elegante, quindi. (Notare che sono richiesti i caratteri ^ e $, a meno che non si desideri una corrispondenza parziale.) Tuttavia, se si desidera effettivamente restituire le voci corrispondenti, mi piace questa soluzione.
Darren Cook,

2
L'ultimo commento contiene un errore di sintassi: / $ dovrebbe essere $ / invece.
Gogowitsch,

1
@DarrenCook, per quanto ne so, un cast bool funzionerebbe anche (bool) preg_grep ('/ ^'. Preg_quote ($ ago). '$ /', $ A), poiché un array vuoto verrebbe lanciato su false
arraintxo

8
Sembra che il modo più semplice per andare sia semplicemente convertire in minuscolo.
Joshua Dance,

229

La cosa ovvia da fare è semplicemente convertire il termine di ricerca in minuscolo:

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

ovviamente se ci sono lettere maiuscole nell'array, devi prima farlo:

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

e cerca quello. Non ha senso fare strtolowerl'intero array con ogni ricerca.

La ricerca di array è tuttavia lineare. Se hai un array di grandi dimensioni o hai intenzione di farlo molto, sarebbe meglio mettere i termini di ricerca in chiave dell'array in quanto questo sarà un accesso molto più veloce:

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

poi

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

L'unico problema qui è che le chiavi dell'array devono essere univoche, quindi se si verifica una collisione (ad es. "Uno" e "uno") si perderanno tutti tranne uno.


23
Questa dovrebbe essere la risposta accettata. L'aggiunta di espressioni regolari a volte crea solo 2 problemi.
Joshua Dance,

1
Array_flip non sarebbe una soluzione ancora più veloce, invece di array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo,

una riga: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew

1
@Akira Yamamoto - che cos'è la modifica della "sintassi fissa" ? Non siamo autorizzati a correggere il codice qui. L'ho riavviato.
Funk Forty Niner


113
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Dalla documentazione


3
Dovresti bloccare il codice (o qualsiasi altra cosa) che ricevi da qualche altra parte.
cletus,

3
Giusto per essere chiari. Non è una critica. Solo un suggerimento (e solo la mia opinione, niente di ufficiale). :) Almeno se copio un frammento di codice da una pagina, lo bloccherò citandolo.
cletus,

3
Inoltre, l'utilizzo di un blocco di codice lo descrive meglio, in quanto è "codice". Il blocco delle quotazioni non consente di formattarlo correttamente.
Tyler Carter,

Sono corretto, dopo aver utilizzato il pulsante effettivo per aggiungere >a ogni riga, funziona. Sono solo abituato a mettere manualmente >la prima riga.
Tyler Carter,

Sono abituato a usare ctrl-Q per farlo. Questo ha un problema con i blocchi di codice perché per qualche motivo avvolge le linee. Non chiedermi perché. Ma puoi semplicemente correggerlo o inserire manualmente >all'inizio di ogni riga.
cletus,

50
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Fonte: pagina di manuale di php.net in_array.


Se sai cosa c'è nell'array, puoi tralasciare array_map; ma questo è un buon esempio.
Don

2
L'ho fatto davvero. Perché mappare l'array ad ogni chiamata è, beh, ridicolo.
cletus,

Inoltre, supponendo (come Chacha) che questo provenga direttamente dai documenti, è meglio bloccare la citazione.
cletus,

10

Supponiamo che tu voglia utilizzare in_array, ecco come puoi rendere insensibile il caso di ricerca.

Case insensitive in_array ():

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

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

}

Distinzione maiuscole / minuscole normale:

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

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

     {
        echo "found";
     }

}

2

Quanto sopra è corretto se assumiamo che le matrici possano contenere solo stringhe, ma le matrici possono contenere anche altre matrici. Anche la funzione in_array () può accettare un array per $ ago, quindi strtolower ($ ago) non funzionerà se $ ago è un array e array_map ('strtolower', $ haystack) non funzionerà se $ haystack contiene altri array, ma genererà "Avviso PHP: strtolower () prevede che il parametro 1 sia stringa, array dato".

Esempio:

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

Così ho creato una classe di supporto con i metodi pertinenti, per effettuare controlli in_array () sensibili al maiuscolo / minuscolo. Sto anche usando mb_strtolower () invece di strtolower (), quindi è possibile utilizzare altre codifiche. Ecco il codice:

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

1

Ho scritto una semplice funzione per verificare la presenza di un valore insensibile in un array il codice è sotto.

funzione:

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

come usare:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));

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

}

Finalmente. Ci sono voluti 8 anni prima che qualcuno facesse un passo avanti e fornisse la tecnica più efficiente - un inizioreturn . Quando è necessario solo trovare 1 dell'ago, è inutile continuare a iterare dopo averlo trovato. Vorrei correggere un errore di battitura, inserire il concetto $ rigoroso e apportare alcuni perfezionamenti, forse qualcosa di simile a 3v4l.org/WCTi2 . Questo post non è perfetto, ma il suo cuore è nel posto giusto.
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);

1
Aggiungi una descrizione della soluzione che stai proponendo.
il_raffa,

-2
  • in_array accetta questi parametri: in_array (ricerca, matrice, tipo)
  • se il parametro di ricerca è una stringa e il parametro type è impostato su TRUE, la ricerca fa distinzione tra maiuscole e minuscole.
  • quindi per fare in modo che la ricerca ignori il caso, basterebbe usarlo in questo modo:

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

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


6
Il terzo parametro controlla se viene controllato o meno il tipo di variabile, non il caso . Quando trueverranno utilizzati confronti di tipo rigorosi, ad es '1' !== 1. Quando falseverrà utilizzato il tipo di giocoleria, ad es '1' == 1. Vedi php.net/in_array e php.net/manual/en/types.comparisons.php per la documentazione.
Leepowers
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.