জেনেরিক অভিধানের ক্ষেত্রে সংবেদনশীল অ্যাক্সেস


244

আমার কাছে একটি অ্যাপ্লিকেশন রয়েছে যা পরিচালিত ঘড়ি ব্যবহার করে। এই dllsগুলির মধ্যে একটি জেনেরিক অভিধানটি ফেরত দেয়:

Dictionary<string, int> MyDictionary;  

অভিধানটিতে উপরের এবং লোয়ার কেস সহ কী রয়েছে।

অন্যদিকে আমি সম্ভাব্য কী (স্ট্রিং) এর একটি তালিকা পাচ্ছি তবে আমি মামলার গ্যারান্টি দিতে পারি না। আমি কীগুলি ব্যবহার করে অভিধানে মান পেতে চেষ্টা করছি। তবে অবশ্যই আমার সাথে কেস মেলে না বলে নিম্নলিখিতটি ব্যর্থ হবে:

bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );  

আমি আশা করছিলাম যে ট্রাইগেটভ্যালুতে এমএসডিএন ডকটিতে উল্লিখিত মত এড়িয়ে যাওয়া মামলার পতাকা থাকবে তবে এটি জেনেরিক অভিধানের জন্য বৈধ নয় বলে মনে হচ্ছে।

মূল কেসটিকে উপেক্ষা করে সেই অভিধানটির মান পাওয়ার কোনও উপায় আছে কি? যথাযথ স্ট্রিংকম্পার.আর্ডিনালআইগনোর কেস প্যারামিটার দিয়ে অভিধানের একটি নতুন অনুলিপি তৈরি করার চেয়ে আরও ভাল কাজ কি আছে ?


সম্পর্কিত পোস্টগুলি - সি # , সি # অভিধানে
আরবিটি

উত্তর:


514

StringComparerআপনি যে মুহুর্তে মূল্য পাওয়ার চেষ্টা করছেন সেখানে নির্দিষ্ট করার কোনও উপায় নেই । আপনি যদি এটির বিষয়ে চিন্তা করেন "foo".GetHashCode()এবং "FOO".GetHashCode()সম্পূর্ণ ভিন্ন হন তবে কোনও কেস-সংবেদনশীল হ্যাশ মানচিত্রে কোনও কেস-সংবেদনশীল প্রাপ্তিকে কার্যকর করতে পারে এমন কোনও যুক্তিযুক্ত উপায় নেই।

আপনি তবে প্রথমে কেস-সংবেদনশীল অভিধান তৈরি করে এই ব্যবহার করতে পারেন:

var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);

বা বিদ্যমান কেস-সংবেদনশীল অভিধানের বিষয়বস্তু সহ একটি নতুন কেস-সংবেদনশীল অভিধান তৈরি করুন (যদি আপনি নিশ্চিত হন যে কোনও ক্ষেত্রে সংঘর্ষের ঘটনা নেই): -

var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);

এই নতুন অভিধান তারপর ব্যবহার GetHashCode()উপর বাস্তবায়ন StringComparer.OrdinalIgnoreCaseযাতে comparer.GetHashCode("foo")এবং comparer.GetHashcode("FOO")আপনি একই মান দিতে।

পর্যায়ক্রমে, অভিধানে যদি কয়েকটি কয়েকটি উপাদান থাকে এবং / অথবা আপনার কেবল একবার বা দুবার অনুসন্ধান করতে হয় তবে আপনি মূল IEnumerable<KeyValuePair<TKey, TValue>>অভিধানটিকে একটি হিসাবে বিবেচনা করতে পারেন এবং কেবল এটির পুনরাবৃত্তি করতে পারেন: -

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;

বা আপনি যদি পছন্দ করেন তবে লিনকিউ ছাড়াই: -

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
int? value;
foreach (var element in myDictionary)
{
  if (String.Equals(element.Key, myKey, comparer))
  {
    value = element.Value;
    break;
  }
}

এটি আপনাকে একটি নতুন ডেটা কাঠামো তৈরির ব্যয় সাশ্রয় করে, কিন্তু বিনিময়ে একটি অনুসন্ধানের জন্য ও (1) এর পরিবর্তে ও (এন) হয়।


প্রকৃতপক্ষে এটি বোধগম্য হয়। ব্যাখ্যার জন্য অনেক ধন্যবাদ।
টোকটক

1
পুরানো অভিধানটি চারপাশে রাখার এবং নতুন ইনস্ট্যান্ট করার কোনও কারণ নেই কারণ যে কোনও ক্ষেত্রে-সংঘর্ষগুলির ফলে এটি বিস্ফোরণ ঘটবে। আপনি যদি জানেন যে আপনি সংঘর্ষগুলি পাবেন না তবে আপনি শুরু থেকে সংবেদনশীল ক্ষেত্রেও ব্যবহার করতে পারেন।
রাইস বেভিলাকোয়া

2
দশ বছর কেটে গেছে যে আমি। নেট ব্যবহার করে চলেছি এবং আমি এখন এটি আবিষ্কার করেছি !! আপনি কারেন্টকালচারের পরিবর্তে অর্ডিনাল ব্যবহার করবেন কেন?
জর্দান

ঠিক আছে, এটি আপনার পছন্দসই আচরণের উপর নির্ভর করে। যদি ব্যবহারকারী ইউআই এর মাধ্যমে কী সরবরাহ করে (বা যদি আপনাকে উদাহরণস্বরূপ ss এবং ß সমান বিবেচনা করতে হয়) তবে আপনাকে আলাদা সংস্কৃতি ব্যবহার করতে হবে, তবে মানটি হ্যাশম্যাপ থেকে আগত কী হিসাবে ব্যবহৃত হচ্ছে তা দেওয়া হচ্ছে বাহ্যিক নির্ভরতা, আমি মনে করি 'অর্ডিনালকালচার' একটি যুক্তিসঙ্গত অনুমান।
আইয়েন

1
default(KeyValuePair<T, U>)না null- এটি একটি KeyValuePairযেখানে Key=default(T)এবং Value=default(U)। সুতরাং আপনি ?.লিনকিউ উদাহরণে অপারেটরটি ব্যবহার করতে পারবেন না ; আপনাকে ধরে নিতে হবে FirstOrDefault()এবং তারপরে (এই বিশেষ ক্ষেত্রে) চেক করতে হবে কিনা তা দেখার জন্য Key == null
asherber

38

আপনার জন্য সেখানে লাইনকিয়ার্স যারা কখনও নিয়মিত অভিধান নির্মাণকারী ব্যবহার করেন না:

myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)

8

এটি খুব মার্জিত নয় তবে আপনি অভিধানটি তৈরি করতে পারবেন না, এবং আপনার যা প্রয়োজন তা একটি নোংরা হ্যাক, এটি সম্পর্কে কীভাবে:

var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault();
    if (item != null)
    {
        TheValue = item.Value;
    }

13
বা কেবল এটি: নতুন অভিধান <স্ট্রিং, ইন্ট> (অন্যান্য ডিক্ট, স্ট্রিংকম্পেরার কর্নার কালচারআইগনরেস কেস);
জর্ডান

6
".NET ফ্রেমওয়ার্কের স্ট্রিংগুলি ব্যবহারের জন্য সেরা অভ্যাসগুলি" এর ToUpperInvariantপরিবর্তে ব্যবহার করুন ToLowermsdn.microsoft.com/en-us/library/dd465121%28v=vs.110%29.aspx
ফ্রেড

এটি আমার পক্ষে ভাল ছিল, যেখানে আমাকে সংবেদনশীল পদ্ধতিতে চাবি পরীক্ষা করতে হয়েছিল। আমি এটি আরও কিছুটা প্রবাহিত করেছিvar item = MyDictionary.FirstOrDefault(x => x.Key.ToUpperInvariant() == keyValueToCheck.ToUpperInvariant());
জয়

শুধু কেন নয় dict.Keys.Contains("bla", appropriate comparer)? তদ্ব্যতীত, আপনি সি ও # তে কীভালিউইপায়ার স্ট্রাক্ট হওয়ায় আপনি ফার্স্টআরডিফল্টের জন্য বাতিল হবেন না।
নওফাল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.