PHP-нечутлива до in_array функція


131

Чи можливо провести порівняння з урахуванням регістру при використанні in_arrayфункції?

Отже, з таким джерелом:

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

Усі наступні пошукові запити повертають би істину:

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

Яка функція чи набір функцій зробили б те саме? Я не думаю, що in_arrayсам це може зробити.

Відповіді:


101

Ви можете використовувати preg_grep():

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

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

37
використання регулярних виразів не є хорошим рішенням, оскільки це може бути повільним ... можливо, array_map швидше
phil-opp

5
Для того, щоб зробити його заміною для in_array, повертаючи логічне значення, воно стає: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). То не так елегантно. (Зверніть увагу, що символи ^ та $ потрібні, якщо не бажано часткового узгодження.) Однак якщо ви дійсно хочете, щоб відповідні записи повернулися, мені подобається це рішення.
Даррен Кук

2
Останній коментар містить синтаксичну помилку: / $ замість має бути $ /.
Гогович

1
@DarrenCook, наскільки я знаю Ій кидок також буде працювати (BOOL) preg_grep ( '/ ^' preg_quote ($ голки) '$ /', $ а ..), А порожній масив буде відкидати брехню
arraintxo

8
Здається, простіший спосіб - просто перетворитись на малі регістри.
Танець Джошуа

229

Очевидно, що потрібно просто перетворити пошуковий термін у малі регістри:

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

звичайно, якщо в масиві є великі літери, вам потрібно зробити це спочатку:

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

і пошук цього. Немає сенсу робити strtolowerвесь масив при кожному пошуку.

Однак пошук масивів лінійний. Якщо у вас є великий масив або ви збираєтеся робити це багато, то краще буде покласти пошукові терміни в ключ масиву, оскільки це буде набагато швидшим доступом:

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

тоді

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

Єдине питання полягає в тому, що ключі масиву повинні бути унікальними, тому якщо у вас зіткнення (наприклад, "Один" і "Один"), ви втратите все, крім одного.


23
Це має бути прийнятою відповіддю. Додавання регулярних виразів іноді викликає 2 проблеми.
Танець Джошуа

1
Чи не array_flip тут буде ще швидшим рішенням замість array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo

один рядок: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Андрій

1
@Akira Yamamoto - що з редагуванням "виправити синтаксис" ? Нам тут заборонено виправляти код. Я відкотив її назад.
Funk Forty Niner

Або використовуйте 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));
}

З документації


3
Вам слід заблокувати котирування коду (або що-небудь справді), яке ви отримуєте з десь іншого.
клент

3
Просто, щоб було зрозуміло. Це не критика. Просто пропозиція (і тільки моя думка, нічого офіційного). :) Принаймні, якщо я скопіюю фрагмент коду зі сторінки, я його заблокую.
клент

3
Крім того, використання блоку коду краще описує його, оскільки це "код". Блокування при цитуванні не дозволяє його правильно відформатувати.
Тайлер Картер

Я виправлений, після використання фактичної кнопки для додавання >до кожного рядка вона працює. Я просто звик вручну ставити >перший рядок.
Тайлер Картер

Я звик використовувати ctrl-Q для цього. У цьому є одна проблема з кодовими блоками, оскільки вона чомусь загортає рядки. Не питайте мене, чому. Але ви можете просто виправити це або вручну поставити >на початку кожного рядка.
клент

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

Джерело: сторінка керівництва php.net in_array.


Якщо ви знаєте, що є в масиві, ви можете залишити мапу array_map; але це хороший приклад.
Дон

2
Я насправді. Тому, що відображення масиву на кожен дзвінок є, ну, смішним.
клент

Крім того, якщо припустити (як Chacha) це надходить безпосередньо з документів, краще блокувати його цитатами.
клент

10

Скажімо, ви хочете використовувати in_array, ось як можна зробити пошуковий вираз нечутливим.

Нечутливий до справи in_array ():

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

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

}

Звичайний регістр:

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

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

     {
        echo "found";
     }

}

2

Сказане вище є правильним, якщо вважати, що масиви можуть містити лише рядки, але масиви можуть містити й інші масиви. Також функція in_array () може приймати масив для $ needle, тому strtolower ($ needle) не працюватиме, якщо $ needle - це масив, а array_map ('strtolower', $ копиця сіна) не працюватиме, якщо $ haystack містить інше масивів, але це призведе до "попередження PHP: strtolower () очікує, що параметр 1 буде рядком, задано масив".

Приклад:

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

Тому я створив клас помічників за допомогою релевантних методів, щоб зробити чутливі до регістру та невідчутливі до регістру перевірки in_array (). Я також використовую mb_strtolower () замість strtolower (), тому можна використовувати інші кодування. Ось код:

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

Я написав просту функцію, щоб перевірити наявність нечутливого значення в масиві, який знаходиться внизу.

функція:

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

як використовувати:

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

}

Нарешті. Минуло 8 років, перш ніж хтось піднявся і забезпечив найефективнішу техніку - раннюreturn . Коли потрібно лише знайти 1 голки, безглуздо зберігати ітерацію після її знаходження. Я б поправив помилку, виписав $ строгу концепцію і вніс деякі уточнення, можливо, щось наближене до 3v4l.org/WCTi2 . Ця публікація не є досконалою, але її серце знаходиться в потрібному місці.
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
Додайте опис запропонованого рішення.
il_raffa

-2
  • in_array приймає ці параметри: in_array (пошук, масив, тип)
  • якщо параметр пошуку - це рядок, а для параметра типу встановлено значення TRUE, пошук залежить від регістру.
  • тож для того, щоб пошук ігнорував випадок, досить було б використовувати його так:

$ a = масив ("один", "два", "три", "чотири");

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


6
Третій параметр керує тим, перевіряється чи ні тип змінної, не так . Коли trueбудуть використані суворі порівняння типу, наприклад '1' !== 1. При використанні falseжонглювання типу, наприклад '1' == 1. Див. Php.net/in_array та php.net/manual/en/types.comparisons.php для документації.
leepowers
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.