Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธีเช็คว่า String Array มีคำเฉพาะเจาะจงใน C#

การตรวจสอบว่า Array/List ของ String มีค่าที่ต้องการหรือไม่ มีหลายวิธี แตกต่างใน Performance และ Features

ตัวอย่างข้อมูล

string[] fruits = { "Apple", "Banana", "Cherry", "Date", "Elderberry" };

วิธีที่ 1: Array.Contains / List.Contains (Simple, Case-Sensitive)

bool hasBanana = fruits.Contains("Banana");     // true
bool hasMango = fruits.Contains("Mango");       // false
bool hasBANANA = fruits.Contains("BANANA");     // false (Case-Sensitive!)
  • O(N) Linear Search
  • ใช้ Equality Comparer Default (Ordinal Case-Sensitive)

วิธีที่ 2: LINQ Any() + StringComparison (Case-Insensitive)

bool hasBananaCI = fruits.Any(f => f.Equals("banana", StringComparison.OrdinalIgnoreCase)); // true
bool hasMangoCI = fruits.Any(f => f.Equals("mango", StringComparison.OrdinalIgnoreCase));   // false
  • Short-circuit (หยุดเจอตัวแรก)
  • รองรับ StringComparison ทุกแบบ

วิธีที่ 3: HashSet<T> (O(1) Lookup - สำหรับหลายครั้ง)


// สร้าง HashSet ครั้งเดียว (Pre-compute)
var fruitSet = new HashSet<string>(fruits, StringComparer.OrdinalIgnoreCase);

// Lookup หลายครั้ง - เร็วมาก
bool hasBanana = fruitSet.Contains("banana");      // true
bool hasBANANA = fruitSet.Contains("BANANA");      // true
bool hasMango = fruitSet.Contains("mango");        // false

วิธีที่ 4: Array.IndexOf / Array.FindIndex

int index = Array.IndexOf(fruits, "Cherry"); // 2 (Index)
int indexCI = Array.FindIndex(fruits, f => f.Equals("cherry", StringComparison.OrdinalIgnoreCase)); // 2

bool found = index >= 0;

วิธีที่ 5: LINQ FirstOrDefault / SingleOrDefault

// หา Object เต็ม (ไม่ใช่แค่ bool)
string found = fruits.FirstOrDefault(f => f.Equals("banana", StringComparison.OrdinalIgnoreCase));
// คืน "Banana" หรือ null

string exact = fruits.SingleOrDefault(f => f == "Cherry"); // คืน "Cherry" (ต้องมี 1 ตัวพอดี)

Benchmark (10,000 Items, 1000 Lookups)

Method Time (ms) Note
Array.Contains (Case-Sensitive) ~15 Baseline
LINQ Any (OrdinalIgnoreCase) ~45 Delegate Overhead
HashSet.Contains (OrdinalIgnoreCase) ~0.5 Fastest for Repeated Lookups
Array.IndexOf ~12 Slightly Faster than Contains

Best Practice แบบสรุป

Scenario Recommended
Check ครั้งเดียว, Case-Sensitive array.Contains(value)
Check ครั้งเดียว, Case-Insensitive array.Any(v => v.Equals(val, StringComparison.OrdinalIgnoreCase))
Check หลายครั้ง (Repeated Lookups) สร้าง HashSet<string>(array, StringComparer.OrdinalIgnoreCase) แล้ว .Contains()
ต้องการ Index/Object Array.FindIndex / FirstOrDefault
Sorted Array Array.BinarySearch (O(log N))

ตัวอย่างครบถ้วน

static void Main()
{
    string[] fruits = { "Apple", "Banana", "Cherry" };
    
    // 1. Simple
    Console.WriteLine($"Contains 'Banana': {fruits.Contains("Banana")}"); // True
    
    // 2. Case-Insensitive Once
    Console.WriteLine($"Any 'banana' (CI): {fruits.Any(f => f.Equals("banana", StringComparison.OrdinalIgnoreCase))}"); // True
    
    // 3. Repeated Lookups -> HashSet
    var fruitSet = new HashSet(fruits, StringComparer.OrdinalIgnoreCase);
    Console.WriteLine($"HashSet 'BANANA': {fruitSet.Contains("BANANA")}"); // True
    Console.WriteLine($"HashSet 'Mango': {fruitSet.Contains("Mango")}");   // False
    
    // 4. Get Item
    string found = fruits.FirstOrDefault(f => f.StartsWith("B", StringComparison.OrdinalIgnoreCase));
    Console.WriteLine($"StartsWith B: {found}"); // "Banana"
}