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ć.

Odpowiedzi:


102

możesz użyć preg_grep():

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

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

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.


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


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

Z dokumentacji


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.


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

}

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

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

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

}

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

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

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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.