Fungsi in_array case-insensitive PHP

131

Apakah mungkin untuk melakukan perbandingan case-insensitive ketika menggunakan in_arrayfungsi?

Jadi dengan array sumber seperti ini:

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

Semua pencarian berikut akan mengembalikan true:

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

Fungsi atau serangkaian fungsi apa yang akan melakukan hal yang sama? Saya tidak berpikir in_arraysendiri bisa melakukan ini.

leepower
sumber

Jawaban:

101

Anda bisa menggunakan preg_grep():

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

print_r( preg_grep( "/ONe/i" , $a ) );
ghostdog74
sumber
37
menggunakan ekspresi reguler bukan solusi yang baik, karena bisa lambat ... mungkin array_map lebih cepat
phil-opp
5
Untuk membuat drop-in pengganti in_array, kembali bool, menjadi: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Tidak begitu elegan, kalau begitu. (Perhatikan ^ dan $ karakter diperlukan, kecuali jika diinginkan sebagian pencocokan.) Namun jika Anda benar-benar ingin entri yang cocok dikembalikan, saya suka solusi ini.
Darren Cook
2
Komentar terakhir mengandung kesalahan sintaks: / $ seharusnya $ / sebagai gantinya.
Gogowitsch
1
@ DarrenCook sejauh yang saya tahu bool cast juga akan bekerja (bool) preg_grep ('/ ^'. Preg_quote ($ needle). '$ /', $ A), karena array kosong akan dibuang ke false
arraintxo
8
Sepertinya cara termudah untuk pergi adalah dengan hanya mengkonversi ke huruf kecil.
Joshua Dance
229

Yang jelas harus dilakukan adalah hanya mengubah istilah pencarian menjadi huruf kecil:

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

tentu saja jika ada huruf besar dalam array Anda harus melakukan ini terlebih dahulu:

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

dan cari itu. Tidak ada gunanya melakukan strtolowerpada seluruh array dengan setiap pencarian.

Namun mencari array adalah linear. Jika Anda memiliki array besar atau Anda akan sering melakukan ini, akan lebih baik untuk meletakkan istilah pencarian di dalam kunci array karena ini akan menjadi akses yang jauh lebih cepat:

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

kemudian

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

Satu-satunya masalah di sini adalah bahwa kunci array harus unik sehingga jika Anda memiliki tabrakan (misalnya "Satu" dan "satu") Anda akan kehilangan semua kecuali satu.

cletus
sumber
23
Ini harus menjadi jawaban yang diterima. Menambahkan ekspresi reguler terkadang hanya membuat 2 masalah.
Joshua Dance
1
Bukankah array_flip di sini menjadi solusi yang lebih cepat, daripada array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo
satu baris: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew
1
@ Akira Yamamoto - ada apa dengan edit "memperbaiki sintaks" ? Kami tidak diizinkan untuk memperbaiki kode di sini. Aku menggulungnya kembali.
Funk Forty Niner
Atau gunakan 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));
}

Dari Dokumentasi

Tyler Carter
sumber
3
Anda harus memblokir kode kuota (atau apa pun yang benar-benar) Anda dapatkan dari tempat lain.
cletus
3
Untuk lebih jelasnya. Itu bukan kritik. Hanya saran (dan hanya pendapat saya, tidak ada yang resmi). :) Setidaknya jika saya menyalin cuplikan kode dari halaman, saya akan memblokir penawarannya.
cletus
3
Plus, menggunakan blok kode lebih baik menggambarkannya, karena 'kode'. Blokir kutipan tidak memungkinkan untuk diformat dengan benar.
Tyler Carter
Saya berdiri dikoreksi, setelah menggunakan tombol aktual untuk menambahkan >ke setiap baris, itu berhasil. Saya hanya terbiasa menempatkan secara manual >pada baris pertama.
Tyler Carter
Saya terbiasa menggunakan ctrl-Q untuk melakukannya. Itu memiliki satu masalah dengan blok kode karena untuk beberapa alasan ia membungkus baris. Jangan tanya kenapa. Tapi Anda bisa memperbaikinya atau secara manual menempatkan >di awal setiap baris.
cletus
50
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Sumber: halaman buku panduan php.net in_array.

Gazler
sumber
Jika Anda tahu apa yang ada di dalam array, Anda dapat meninggalkan array_map; tapi ini adalah contoh yang bagus.
Don
2
Sebenarnya saya lakukan. Karena memetakan array pada setiap panggilan itu, well, menggelikan.
cletus
Juga, dengan asumsi (seperti Chacha) ini datang langsung dari dokumen, lebih baik untuk memblokir penawarannya.
cletus
10

Katakanlah Anda ingin menggunakan in_array, di sini adalah bagaimana Anda dapat membuat case pencarian tidak sensitif.

In_array case-insensitive ():

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

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

}

Peka huruf besar-kecil:

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

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

     {
        echo "found";
     }

}
Mike Q
sumber
2

Di atas benar jika kita mengasumsikan bahwa array hanya dapat berisi string, tetapi array juga dapat mengandung array lain. Juga fungsi in_array () dapat menerima array untuk $ needle, jadi strtolower ($ needle) tidak akan berfungsi jika $ needle adalah array dan array_map ('strtolower', $ haystack) tidak akan berfungsi jika $ haystack mengandung lainnya array, tetapi akan menghasilkan "PHP warning: strtolower () mengharapkan parameter 1 menjadi string, array diberikan".

Contoh:

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

Jadi saya membuat kelas pembantu dengan metode releveant, untuk melakukan pemeriksaan case-sensitive dan case-insensitive in_array (). Saya juga menggunakan mb_strtolower () alih-alih strtolower (), jadi penyandian lainnya dapat digunakan. Berikut kodenya:

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
sumber
1

Saya menulis fungsi sederhana untuk memeriksa nilai tidak sensitif dalam array kode di bawah ini.

fungsi:

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

Cara Penggunaan:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));
Jake
sumber
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
sumber
Akhirnya. Butuh 8 tahun sebelum seseorang melangkah dan memberikan teknik yang paling efisien - awalreturn . Ketika hanya perlu menemukan 1 jarum, tidak ada gunanya untuk tetap iterasi setelah menemukannya. Saya akan memperbaiki kesalahan ketik, memanggang konsep $ ketat dan membuat beberapa penyempurnaan, mungkin sesuatu yang dekat dengan 3v4l.org/WCTi2 . Posting ini tidak sempurna, tetapi hatinya ada di tempat yang tepat.
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
sumber
1
Tolong, tambahkan deskripsi dari solusi yang Anda usulkan.
il_raffa
-2
  • in_array menerima parameter ini: in_array (pencarian, array, jenis)
  • jika parameter pencarian adalah string dan parameter tipe diatur ke TRUE, pencarian adalah case-sensitive.
  • jadi untuk membuat pencarian mengabaikan case, itu akan cukup untuk menggunakannya seperti ini:

$ a = array ('satu', 'dua', 'tiga', 'empat');

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

pengguna1077915
sumber
6
Parameter ketiga mengontrol apakah tipe atau tidak variabel dicentang, bukan case . Ketika trueperbandingan tipe ketat akan digunakan, mis '1' !== 1. Ketika falsejenis juggling akan digunakan, misalnya '1' == 1. Lihat php.net/in_array dan php.net/manual/en/types.comparisons.php untuk dokumentasi.
Leepowers