ฟังก์ชั่น in_array case-insensitive PHP


131

เป็นไปได้หรือไม่ที่จะทำการเปรียบเทียบแบบตัวพิมพ์เล็กและใหญ่เมื่อใช้in_arrayฟังก์ชัน?

ดังนั้นด้วย 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 เร็ว
ฟิล-OPP

5
จะทำให้มันเป็นแบบเลื่อนแทน in_array count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0)กลับบูลมันจะกลายเป็น: ไม่ค่อยสง่างามแล้ว (โปรดสังเกตว่าต้องใช้อักขระ ^ และ $ ยกเว้นว่าต้องการการจับคู่บางส่วน) อย่างไรก็ตามถ้าคุณต้องการให้ส่งคืนรายการที่ตรงกันจริง ๆ ฉันชอบโซลูชันนี้
Darren Cook

2
ความคิดเห็นล่าสุดมีข้อผิดพลาดทางไวยากรณ์: / $ ควรเป็น $ / แทน
Gogowitsch

1
@DarrenCook เท่าที่ฉันรู้ว่าผู้ส่ง bool ก็สามารถทำงานได้ (bool) preg_grep ('/ ^'. preg_quote ($ เข็ม) '$ /', $ a) เนื่องจากอาร์เรย์ว่างจะถูกส่งเป็นเท็จ
arraintxo

8
ดูเหมือนวิธีที่ง่ายกว่าที่จะไปคือเพียงแปลงเป็นตัวพิมพ์เล็ก
Joshua Dance

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 ข้อ
Joshua Dance

1
array_flip ที่นี่จะไม่เป็นทางออกที่เร็วยิ่งขึ้นแทนที่จะเป็น array_combine หรือไม่ $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo

หนึ่งบรรทัด: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew

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
คุณควรบล็อกโควตโค้ด (หรืออะไรก็ตาม) ที่คุณได้รับจากที่อื่น
cletus

3
เพียงเพื่อให้ชัดเจน มันไม่ใช่การวิจารณ์ เพียงข้อเสนอแนะ (และเฉพาะความเห็นของฉันไม่มีอะไรเป็นทางการ) :) อย่างน้อยถ้าฉันคัดลอกโค้ดจากหน้าฉันจะปิดกั้นอ้างมัน
cletus

3
นอกจากนี้การใช้บล็อกรหัสอธิบายได้ดีกว่าเนื่องจากเป็น 'รหัส' บล็อกข้อความไม่อนุญาตให้ฟอร์แมตอย่างถูกต้อง
Tyler Carter

ฉันยืนถูกต้องหลังจากใช้ปุ่มจริงเพื่อเพิ่ม>ไปยังทุกบรรทัดมันใช้งานได้ ฉันเพิ่งคุ้นเคยกับการใส่>บรรทัดแรก
Tyler Carter

ฉันเคยใช้ ctrl-Q เพื่อทำมัน มันมีปัญหาหนึ่งกับบล็อคโค้ดเพราะด้วยเหตุผลบางอย่างมันก็ขีดเส้น อย่าถามฉันทำไม แต่คุณสามารถแก้ไขหรือใส่>จุดเริ่มต้นของแต่ละบรรทัดด้วยตนเองก็ได้
cletus

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

ที่มา: php.net หน้าคู่มือ in_array


หากคุณรู้ว่ามีอะไรอยู่ในอาร์เรย์คุณสามารถปล่อย array_map ออกมาได้ แต่นี่เป็นตัวอย่างที่ดี
ดอน

2
จริง ๆ แล้วฉันทำ เนื่องจากการจับคู่อาร์เรย์กับการโทรทุกครั้งนั้นเป็นเรื่องที่น่าหัวเราะ
cletus

นอกจากนี้สมมติว่า (เช่น Chacha) สิ่งนี้มาโดยตรงจากเอกสารจะดีกว่าถ้าจะปิดกั้นอ้าง
cletus

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 () สามารถรับอาร์เรย์สำหรับ $ เข็มดังนั้น strtolower ($ เข็ม) จะไม่ทำงานหาก $ needle เป็นอาร์เรย์และ array_map ('strtolower', $ haystack) จะไม่ทำงานหาก $ haystack มีอื่น ๆ อาร์เรย์ แต่จะส่งผลให้ "คำเตือน PHP: strtolower () คาดว่าพารามิเตอร์ 1 จะเป็นสตริง, อาร์เรย์ที่กำหนด"

ตัวอย่าง:

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

ดังนั้นฉันจึงสร้างคลาสผู้ช่วยด้วยวิธีการลดการตรวจสอบ case-sensitive และ case-insensitive 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 (ค้นหา, อาร์เรย์, ประเภท)
  • หากพารามิเตอร์การค้นหาเป็นสตริงและพารามิเตอร์ type ถูกตั้งค่าเป็น TRUE การค้นหาจะคำนึงถึงขนาดตัวพิมพ์
  • ดังนั้นเพื่อให้การค้นหาไม่สนใจตัวพิมพ์เล็กและใหญ่มันก็เพียงพอที่จะใช้มันในลักษณะนี้:

$ a = array ('หนึ่ง', 'สอง', 'สาม', 'สี่');

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


6
ที่สามการควบคุมพารามิเตอร์หรือไม่ว่าประเภทของตัวแปรมีการตรวจสอบไม่ได้เป็นกรณี เมื่อเปรียบเทียบประเภทที่เข้มงวดจะถูกนำมาใช้เช่นtrue '1' !== 1เมื่อประเภทเล่นกลจะถูกนำมาใช้เช่นfalse '1' == 1ดูphp.net/in_arrayและphp.net/manual/th/types.comparisons.phpสำหรับเอกสารประกอบ
leepowers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.