Funkcja in_array bez rozróżniania wielkości liter w PHP

132

Czy podczas korzystania z in_arrayfunkcji możliwe jest porównanie bez rozróżniania wielkości liter ?

Więc z tablicą źródłową taką jak ta:

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

Poniższe wyszukiwania zwróciłyby prawdę:

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

Jaka funkcja lub zestaw funkcji zrobiłby to samo? Nie sądzę, że in_arraysam może to zrobić.

leepowers
źródło

Odpowiedzi:

102

możesz użyć preg_grep():

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

print_r( preg_grep( "/ONe/i" , $a ) );
ghostdog74
źródło
37
używanie wyrażeń regularnych nie jest dobrym rozwiązaniem, ponieważ może być powolne ... może array_map jest szybsze
phil-opp
5
Aby to zamiennik dla in_array, wracając bool, staje się: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Więc nie tak elegancko. (Zwróć uwagę, że znaki ^ i $ są wymagane, chyba że pożądane jest częściowe dopasowanie). Jeśli jednak chcesz, aby pasujące wpisy zostały zwrócone, podoba mi się to rozwiązanie.
Darren Cook,
2
Ostatni komentarz zawiera błąd składniowy: / $ powinno być zamiast tego $ /.
Gogowitsch
1
@DarrenCook, o ile wiem, rzutowanie bool również działałoby (bool) preg_grep ('/ ^'. Preg_quote ($ needle). '$ /', $ A), ponieważ pusta tablica byłaby rzutowana na false
arraintxo
8
Wydaje się, że łatwiejszym sposobem jest po prostu zamiana na małe litery.
Joshua Dance,
235

Oczywistą rzeczą jest po prostu przekonwertowanie wyszukiwanego hasła na małe litery:

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

oczywiście, jeśli w tablicy znajdują się duże litery, musisz najpierw zrobić to:

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

i wyszukaj to. Nie ma sensu zajmować strtolowersię całą tablicą przy każdym wyszukiwaniu.

Przeszukiwanie tablic jest jednak liniowe. Jeśli masz dużą tablicę lub zamierzasz to robić dużo, lepiej byłoby umieścić wyszukiwane hasła w kluczu tablicy, ponieważ będzie to znacznie szybszy dostęp:

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

następnie

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

Jedynym problemem jest to, że klucze tablic muszą być unikalne, więc jeśli wystąpi kolizja (np. „Jeden” i „jeden”), stracisz wszystkie oprócz jednego.

cletus
źródło
24
To powinna być akceptowana odpowiedź. Dodawanie wyrażeń regularnych czasami powoduje tylko 2 problemy.
Joshua Dance
1
Czy array_flip nie byłby tutaj jeszcze szybszym rozwiązaniem zamiast array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo
1
jedna linia: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrzej
1
@Akira Yamamoto - o co chodzi z edycją „poprawionej składni” ? Nie możemy tutaj naprawiać kodu. Odwróciłem to.
Funk Forty Niner
Lub użyj array_change_key_case () secure.php.net/manual/en/function.array-change-key-case.php
boctulus
114
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Z dokumentacji

Tyler Carter
źródło
3
Powinieneś cytować kod blokowy (lub cokolwiek innego), który otrzymujesz z innego miejsca.
cletus
3
Żeby było jasne. To nie jest krytyka. Tylko sugestia (i tylko moja opinia, nic oficjalnego). :) Przynajmniej jeśli skopiuję fragment kodu ze strony, zablokuję cytowanie.
cletus
3
Ponadto użycie bloku kodu lepiej go opisuje, ponieważ jest to „kod”. Cytowanie blokowe nie pozwala na prawidłowe sformatowanie.
Tyler Carter
Stoję poprawione, po użyciu właściwego przycisku, aby dodać >do każdej linii, działa. Jestem po prostu przyzwyczajony do ręcznego umieszczania >w pierwszej linii.
Tyler Carter
Jestem przyzwyczajony do używania ctrl-Q, aby to zrobić. To ma jeden problem z blokami kodu, ponieważ z jakiegoś powodu zawija linie. Nie pytaj mnie dlaczego. Ale możesz po prostu to poprawić lub ręcznie wstawić >na początku każdego wiersza.
cletus
51
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Źródło: strona podręcznika php.net in_array.

Gazler
źródło
Jeśli wiesz, co jest w tablicy, możesz pominąć tablicę_map; ale to jest dobry przykład.
Don
2
Właściwie to zrobiłem. Ponieważ mapowanie tablicy przy każdym wywołaniu jest, no cóż, niedorzeczne.
cletus
Zakładając, że (podobnie jak Chacha) pochodzi to bezpośrednio z dokumentacji, lepiej jest zablokować cytowanie.
cletus
10

Załóżmy, że chcesz użyć tablicy in_array, oto jak możesz ustawić niewrażliwość na wielkość liter w wyszukiwaniu.

In_array () bez rozróżniania wielkości liter:

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

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

}

Normalna wielkość liter:

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

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

     {
        echo "found";
     }

}
Mike Q
źródło
3

Powyższe jest poprawne, jeśli założymy, że tablice mogą zawierać tylko łańcuchy, ale tablice mogą również zawierać inne tablice. Również funkcja in_array () może akceptować tablicę dla $ needle, więc strtolower ($ needle) nie będzie działać, jeśli $ needle jest tablicą, a array_map ('strtolower', $ haystack) nie będzie działać, jeśli $ haystack zawiera inne tablice, ale spowoduje "ostrzeżenie PHP: strtolower () oczekuje, że parametr 1 będzie ciągiem, podana tablica".

Przykład:

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

Dlatego utworzyłem klasę pomocniczą z odpowiednimi metodami, aby przeprowadzać kontrole in_array () z uwzględnieniem wielkości liter i bez uwzględniania wielkości liter. Używam również mb_strtolower () zamiast strtolower (), więc można użyć innych kodowań. Oto kod:

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
źródło
1

Napisałem prostą funkcję, aby sprawdzić niewrażliwą wartość w tablicy, której kod jest poniżej.

funkcjonować:

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

jak używać:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));
Jake
źródło
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
źródło
Wreszcie. Minęło 8 lat, zanim ktoś wkroczył i dostarczył najbardziej wydajną technikę - wczesnąreturn . Gdy trzeba znaleźć tylko 1 igłę, nie ma sensu powtarzać iteracji po jej znalezieniu. Poprawiłbym literówkę, wypaliłbym w koncepcji $ ścisłej i wprowadziłbym pewne udoskonalenia, być może coś zbliżonego do 3v4l.org/WCTi2 . Ten post nie jest doskonały, ale jego serce jest we właściwym miejscu.
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
źródło
1
Dodaj opis proponowanego rozwiązania.
il_raffa
0
$user_agent = 'yandeX';
$bots = ['Google','Yahoo','Yandex'];        
        
foreach($bots as $b){
     if( stripos( $user_agent, $b ) !== false ) return $b;
}
Arthur Veselov
źródło
Chociaż ten kod może odpowiedzieć na pytanie, zapewnia dodatkowy kontekst dotyczący tego, dlaczego i / lub jak ten kod odpowiada, poprawia jego długoterminową wartość.
Derviş Kayımbaşıoğlu
-2
  • in_array akceptuje następujące parametry: in_array (szukaj, tablica, typ)
  • jeśli parametr wyszukiwania jest ciągiem, a parametr typu ma wartość TRUE, wyszukiwanie jest rozróżniane z uwzględnieniem wielkości liter.
  • więc aby wyszukiwanie ignorowało wielkość liter, wystarczy użyć tego w następujący sposób:

$ a = tablica ('jeden', 'dwa', 'trzy', 'cztery');

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

user1077915
źródło
6
Trzeci parametr kontroluje, czy typ zmiennej jest sprawdzany, a nie wielkość liter . Gdy trueużywane będą ścisłe porównania typów, np '1' !== 1. Gdy falseżonglerka typami będzie używana, np '1' == 1. Zobacz php.net/in_array i php.net/manual/en/types.comparisons.php, aby uzyskać dokumentację.
leepowers