কেস-সংবেদনশীল তালিকা অনুসন্ধান


144

আমার কাছে একটি তালিকা testListরয়েছে যার মধ্যে একটি গুচ্ছ স্ট্রিং রয়েছে। আমি testListতালিকাটিতে ইতিমধ্যে বিদ্যমান না থাকলে কেবলমাত্র একটি নতুন স্ট্রিং যুক্ত করতে চাই । অতএব, আমাকে তালিকার কেস-সংবেদনশীল অনুসন্ধান এবং এটিকে দক্ষ করে তোলা দরকার। আমি ব্যবহার করতে পারি না Containsকারণ এটি কেসিংটিকে বিবেচনায় নেয় না। ToUpper/ToLowerপারফরম্যান্সের কারণেও আমি ব্যবহার করতে চাই না । আমি এই পদ্ধতিটি পেরিয়ে এসেছি, যা কাজ করে:

    if(testList.FindAll(x => x.IndexOf(keyword, 
                       StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
       Console.WriteLine("Found in list");

এটি কাজ করে তবে এটি আংশিক শব্দের সাথেও মেলে। তালিকায় যদি "ছাগল" থাকে তবে আমি "ওট" যুক্ত করতে পারি না কারণ এটি দাবি করে যে "ওট" ইতিমধ্যে তালিকায় রয়েছে। কোনও ক্ষেত্রে সংবেদনশীল পদ্ধতিতে দক্ষতার সাথে তালিকাগুলি অনুসন্ধান করার কোনও উপায় আছে, যেখানে শব্দগুলির সাথে হুবহু মিল থাকতে হয়? ধন্যবাদ

উত্তর:


180

স্ট্রিং.ইনডেক্সফের পরিবর্তে, আপনার আংশিক ম্যাচ না রয়েছে তা নিশ্চিত করতে স্ট্রিং.একুয়ালগুলি ব্যবহার করুন । প্রতিটি উপাদান যেমন যায় ততই ফাইন্ডএল ব্যবহার করবেন না, ফাইন্ড ইন্ডেক্স ব্যবহার করুন (এটি হিট হওয়ার প্রথমটিতে থামবে)।

if(testList.FindIndex(x => x.Equals(keyword,  
    StringComparison.OrdinalIgnoreCase) ) != -1) 
    Console.WriteLine("Found in list"); 

পর্যায়ক্রমে কিছু লিনকিউ পদ্ধতি ব্যবহার করুন (এটি হিট প্রথমটিতেও থামবে)

if( testList.Any( s => s.Equals(keyword, StringComparison.OrdinalIgnoreCase) ) )
    Console.WriteLine("found in list");

কেবলমাত্র যুক্ত করার জন্য, কয়েকটি দ্রুত পরীক্ষায় এটি মনে হয় যে প্রথম পদ্ধতিটি প্রায় 50% দ্রুত। হতে পারে অন্য কেউ তা নিশ্চিত / অস্বীকার করতে পারে।
বৃহস্পতিবার

8
.NET 2.0 হিসাবে, এটি এখন সহজেই সম্পন্ন হয় - নীচে শ্যাক্সবাইয়ের উত্তরটি দেখুন।
জো

3
কন্টেনস মেথড শ্যাক্সবি'র রেফারেন্সিং (এতে একটি ওভারলোড রয়েছে যা আইক্যুয়ালিম্প্যাকার নেয়) লিনকিউ-র অংশ, তাই এটি নেট .০.০ থেকে অবশ্যই পাওয়া যায়নি। স্রেফ স্ট্রিংকম্পার ক্লাসটি প্রায় কিছু সময়ের জন্য হয়েছে। তালিকার <T> তে সেই পদ্ধতি নেই, না অ্যারেলিস্ট বা স্ট্রিংকলেকশন নেই (যে জিনিসগুলি তিনি সহজেই তাঁর 'তালিকা' হিসাবে উল্লেখ করতে পারতেন)।
অ্যাডাম সিলস

ঠিক আছে, যেহেতু আসলে আমার সূচকের দরকার ছিল, এটি অবশ্যই আমার পক্ষে সেরা উত্তর ছিল।
নাইয়ারগডস

1
প্রথম সমাধান List<>.Exists(Predicate<>)উদাহরণ পদ্ধতি ব্যবহার করা উচিত । আরও মনে রাখবেন যে তালিকায় যদি nullএন্ট্রি থাকে তবে এটি ফুটিয়ে উঠতে পারে। সেক্ষেত্রে এটির keyword.Equals(x, StringComparison.OrdinalIgnoreCase)চেয়ে বেশি বলা নিরাপদ x.Equals(keyword, StringComparison.OrdinalIgnoreCase)(যদি আপনি গ্যারান্টি দিতে পারেন যে এটি keywordকখনই বাতিল নয়)।
জেপ্পে স্টিগ নীলসেন

359

আমি বুঝতে পেরেছি এটি একটি পুরানো পোস্ট, তবে অন্য যে কেউ সন্ধান করছে সে ক্ষেত্রে আপনি এইরকম ক্ষেত্রে সংবেদনশীল স্ট্রিং সমতা তুলনামূলক সরবরাহ করে ব্যবহার করতে পারেন Contains:

using System.Linq;

// ...

if (testList.Contains(keyword, StringComparer.OrdinalIgnoreCase))
{
    Console.WriteLine("Keyword Exists");
}

এটি এমএসডিএন অনুসারে । নেট 2.0 থেকে পাওয়া যায় ।


21
অবশ্যই এখানে সেরা উত্তর। :)
জো

22
গণনাযোগ্য <টি>। .NET 2.0 এর পরে কন্টেন্টগুলি (আপনি যা উল্লেখ করছেন) প্রায় নেই। কোনও তালিকা নেই <T> .আপনার যে ওভারলোড ব্যবহার করছেন তা অন্তর্ভুক্ত রয়েছে।
অ্যাডাম সিলস

ঠিক আছে তালিকায় <T> তে এ জাতীয় কোনও পদ্ধতি নেই। এবং যদি এটি একটি অলস সংগ্রহ হয়, তার চেয়ে অনেক বেশি বার এটি পুনরাবৃত্তি করতে পারে অন্যান্য এনুম্যুর্যাল <টি> পদ্ধতিগুলি। ইমো, এই পদ্ধতিটি এ জাতীয় ক্ষেত্রে ব্যবহার করা উচিত নয়, কারণ এটি এই ক্ষেত্রে এতটা যৌক্তিক নয়।
সের্গেই লিটভিনভ

40
আমি এই ওভারলোডটি প্রথমে দেখতে পাচ্ছিলাম না, তবে আপনাকে সিস্টেম.লিঙ্ক ব্যবহার করে যুক্ত করা দরকার তখন এটি প্রদর্শিত হবে।
মাইকেল

1
StringComparerবর্গ 2.0 যেহেতু হয়েছে প্রায়, কিন্তু ধারণ করে যে জমিদার 3.5 চালু করা হয়। msdn.microsoft.com/en-us/library/bb339118(v=vs.110).aspx
ডেনিস স্কিডমোর

18

উপরের অ্যাডাম সিলস উত্তরের উপর ভিত্তি করে - এখানে রয়েছে একটি দুর্দান্ত পরিষ্কার এক্সটেনশন পদ্ধতি ... :)

///----------------------------------------------------------------------
/// <summary>
/// Determines whether the specified list contains the matching string value
/// </summary>
/// <param name="list">The list.</param>
/// <param name="value">The value to match.</param>
/// <param name="ignoreCase">if set to <c>true</c> the case is ignored.</param>
/// <returns>
///   <c>true</c> if the specified list contais the matching string; otherwise, <c>false</c>.
/// </returns>
///----------------------------------------------------------------------
public static bool Contains(this List<string> list, string value, bool ignoreCase = false)
{
    return ignoreCase ?
        list.Any(s => s.Equals(value, StringComparison.OrdinalIgnoreCase)) :
        list.Contains(value);
}

10

আপনি স্ট্রিংকম্পার ব্যবহার করতে পারেন:

    var list = new List<string>();
    list.Add("cat");
    list.Add("dog");
    list.Add("moth");

    if (list.Contains("MOTH", StringComparer.OrdinalIgnoreCase))
    {
        Console.WriteLine("found");
    }

1
যতক্ষণ আপনি "সিস্টেম.লিনক ব্যবহার করে" যুক্ত করেন, অন্যথায় আপনি ওভারলোড দেখতে পাবেন না ont
জুলিয়ান মেলভিল

1

ল্যান্স লারসেন উত্তরের উপর ভিত্তি করে - এখানে প্রস্তাবিত স্ট্রিং সহ একটি এক্সটেনশন পদ্ধতি রয়েছে string স্ট্রিংয়ের পরিবর্তে তুলনা করুন qu

আপনি স্ট্রিংয়ের একটি ওভারলোড ব্যবহার করার পরামর্শ দেওয়া হচ্ছে omp এমন একটি তুলনামূলক প্যারামিটার নিয়ে তুলনা করুন omp এই ওভারলোডগুলিই আপনাকে ঠিক করা তুলনা আচরণটি সংজ্ঞায়িত করার অনুমতি দেয় না, সেগুলি ব্যবহার করে আপনার কোডটি অন্যান্য বিকাশকারীদের জন্য আরও পঠনযোগ্য করে তুলবে। [ জোশ ফ্রি @ বিসিএল টিম ব্লগ ]

public static bool Contains(this List<string> source, string toCheck, StringComparison comp)
{
    return
       source != null &&
       !string.IsNullOrEmpty(toCheck) &&
       source.Any(x => string.Compare(x, toCheck, comp) == 0);
}

0

সূচিপত্রের ফলাফলটি বৃহত্তর বা সমান 0 হয় কিনা তা আপনি পরীক্ষা করে দেখছেন, ম্যাচটি স্ট্রিংয়ের যে কোনও জায়গায় শুরু হয় কিনা । এটি 0 এর সমান কিনা তা পরীক্ষা করে দেখুন :

if (testList.FindAll(x => x.IndexOf(keyword, 
                   StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
   Console.WriteLine("Found in list");

এখন "ছাগল" এবং "ওট" মিলবে না, তবে "ছাগল" এবং "ছাগল" যাবে। এড়াতে, আপনি দুটি স্ট্রিংয়ের দৈর্ঘ্য তুলনা করতে পারেন।

এই সমস্ত জটিলতা এড়াতে, আপনি তালিকার পরিবর্তে অভিধান ব্যবহার করতে পারেন। তাদের কীটি ছোট হাতের স্ট্রিং হবে এবং মানটি হবে আসল স্ট্রিং। এইভাবে, কর্মক্ষমতা ক্ষতিগ্রস্থ হয় না কারণ আপনাকে ToLowerপ্রতিটি তুলনার জন্য ব্যবহার করতে হবে না , তবে আপনি এখনও ব্যবহার করতে পারেন Contains


0

নীচে পুরো তালিকার কোনও কীওয়ার্ড অনুসন্ধান করার এবং সেই আইটেমটি সরিয়ে দেওয়ার উদাহরণ দেওয়া হল:

public class Book
{
  public int BookId { get; set; }
  public DateTime CreatedDate { get; set; }
  public string Text { get; set; }
  public string Autor { get; set; }
  public string Source { get; set; }
}

আপনি যদি এমন কোনও বই মুছে ফেলতে চান যাতে পাঠ্য বৈশিষ্ট্যে কিছু কীওয়ার্ড থাকে তবে আপনি কীওয়ার্ডের একটি তালিকা তৈরি করতে এবং বইয়ের তালিকা থেকে এটি সরাতে পারেন:

List<Book> listToSearch = new List<Book>()
   {
        new Book(){
            BookId = 1,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = " test voprivreda...",
            Autor = "abc",
            Source = "SSSS"

        },
        new Book(){
            BookId = 2,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = "here you go...",
            Autor = "bcd",
            Source = "SSSS"


        }
    };

var blackList = new List<string>()
            {
                "test", "b"
            }; 

foreach (var itemtoremove in blackList)
    {
        listToSearch.RemoveAll(p => p.Source.ToLower().Contains(itemtoremove.ToLower()) || p.Source.ToLower().Contains(itemtoremove.ToLower()));
    }


return listToSearch.ToList();

-1

আমারও অনুরূপ সমস্যা ছিল, আমার আইটেমের সূচকের দরকার ছিল তবে এটি সংবেদনশীল হতে হয়েছিল, আমি কয়েক মিনিটের জন্য ওয়েবে ঘুরে দেখলাম এবং কিছুই খুঁজে পেলাম না, তাই এটি সম্পন্ন করার জন্য আমি কেবল একটি ছোট পদ্ধতি লিখেছি, এখানে আমি যা করছি করেছিল:

private static int getCaseInvariantIndex(List<string> ItemsList, string searchItem)
{
    List<string> lowercaselist = new List<string>();

    foreach (string item in ItemsList)
    {
        lowercaselist.Add(item.ToLower());
    }

    return lowercaselist.IndexOf(searchItem.ToLower());
}

এই কোডটিকে একই ফাইলে যুক্ত করুন এবং এটিকে কল করুন:

int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);

ভাগ্য ভালো, এই সাহায্য আশা করি!


1
কেন একটি দ্বিতীয় তালিকা উত্পাদন? এটা খুব দক্ষ নয়। (var i = 0; i <টি আইটেমলিস্ট.কাউন্ট; i++) {যদি (আইটেম.টোলওয়ার () == সার্চ আইটেম.টোলওয়ার ()) {ফিরে আই}}
ওয়েস্ট

আমি মনে করি আমরা জানি না হবে অনুমান।
ডেনি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.