আইডি অভিধান প্রয়োগ রয়েছে কি, অনুপস্থিত কীতে, ছোঁড়ার পরিবর্তে ডিফল্ট মানটি দেয়?


129

অভিধানটিতে সূচকটি কী বাদ দিলে একটি ব্যতিক্রম ছুঁড়ে দেয়। আইডি অভিধানের কোনও বাস্তবায়ন কি এর পরিবর্তে ডিফল্ট (টি) ফিরে আসবে?

আমি "ট্রাইগেটভ্যালু" পদ্ধতি সম্পর্কে জানি তবে লিনাক দিয়ে ব্যবহার করা অসম্ভব।

এটি কি আমার প্রয়োজন মতো দক্ষতার সাথে কাজ করবে ?:

myDict.FirstOrDefault(a => a.Key == someKeyKalue);

আমার মনে হয় না এটি হ্যাশ লুকআপ ব্যবহার করার পরিবর্তে কীগুলি পুনরাবৃত্তি করবে বলে আমি মনে করি।


10
এটি পরে এই প্রশ্নটি দেখুন, এটির
অভিধানটি

2
@ অ্যালান যে নিখরচায় নয়, অনুপস্থিত কীগুলিতে ব্যতিক্রম করবে। এছাড়াও এটি অভিধানে ব্যবহৃত হয় সর্বত্র ডিফল্ট হওয়া উচিত তা সিদ্ধান্ত নিতে হবে। এছাড়াও এই প্রশ্নের বয়স বিবেচনা করুন। আমাদের ছিল না ?? অপারেটর 8 বছর আগে
যেভাবেই

উত্তর:


147

আসলে, এটি মোটেই কার্যকর হবে না।

আপনি সর্বদা একটি এক্সটেনশন পদ্ধতি লিখতে পারেন:

public static TValue GetValueOrDefault<TKey,TValue>
    (this IDictionary<TKey, TValue> dictionary, TKey key)
{
    TValue ret;
    // Ignore return value
    dictionary.TryGetValue(key, out ret);
    return ret;
}

অথবা সি # 7.1 সহ:

public static TValue GetValueOrDefault<TKey,TValue>
    (this IDictionary<TKey, TValue> dictionary, TKey key) =>
    dictionary.TryGetValue(key, out var ret) ? ret : default;

এটি ব্যবহার করে:

  • একটি এক্সপ্রেশন-দেহ পদ্ধতি (সি # 6)
  • একটি আউট ভেরিয়েবল (সি # 7.0)
  • একটি ডিফল্ট আক্ষরিক (সি # 7.1)

2
বা আরও সংক্ষিপ্তভাবে:return (dictionary.ContainsKey(key)) ? dictionary[key] : default(TValue);
পিটার গ্লাক

33
@ পিটারগ্লাক: আরও নিখুঁতভাবে, তবে কম দক্ষতার সাথে ... কী উপস্থিত থাকলে কেন দু'টি চেহারা দেখাবে?
জন স্কিটি

5
@ জোনস্কিট: পিটারকে সংশোধন করার জন্য ধন্যবাদ; কিছুক্ষণের জন্য উপলব্ধি না করে আমি সেই "কম দক্ষ" পদ্ধতিটি ব্যবহার করছি।
জে ব্রায়ান দাম

5
খুব সুন্দর! আমি নির্লজ্জভাবে চুরি করতে যাচ্ছি - এর, এটি কাঁটাচামচ। ;)
জন কোম্বস

3
স্পষ্টতই এমএস সিদ্ধান্ত নিয়েছে যে এটি যুক্ত করার পক্ষে যথেষ্ট ভাল System.Collections.Generic.CollectionExtensions, যেমন আমি কেবল চেষ্টা করেছি এবং এটি সেখানে রয়েছে।
দ্য মায়ার

19

এই এক্সটেনশন পদ্ধতিগুলি বহন করতে সহায়তা করতে পারে ..

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key)
{
    return dict.GetValueOrDefault(key, default(V));
}

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, V defVal)
{
    return dict.GetValueOrDefault(key, () => defVal);
}

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, Func<V> defValSelector)
{
    V value;
    return dict.TryGetValue(key, out value) ? value : defValSelector();
}

3
শেষ ওভারলোডটি আকর্ষণীয়। যেহেতু নির্বাচন করতে কিছুই নয় থেকে , এই কেবল অলস মূল্যায়ন এক ধরনের?
MEMark

1
@ মেমার্ক হ্যাঁ মান নির্বাচনকারী শুধুমাত্র প্রয়োজনে চালিত হয়, সুতরাং এটি একটি উপায়ে অলস মূল্যায়ন হিসাবে বলা যেতে পারে তবে লিনক প্রসঙ্গে যেমন এটি স্থগিত করা হয়নি। তবে এখানে অলস মূল্যায়ন ফ্যাক্টর থেকে নির্বাচন করার জন্য কিছুই নির্ভর করে না , আপনি অবশ্যই নির্বাচক করতে পারেন Func<K, V>
নওফাল

1
এটি কি তৃতীয় পদ্ধতিটি জনসাধারণের জন্য উপযুক্ত কারণ এটি নিজস্বভাবে কার্যকর? এটিই কি আপনি ভাবছেন যে কেউ ল্যাম্বডায় পাস করতে পারে যা বর্তমান সময়কে ব্যবহার করে, বা ... এইচএমএম এর উপর ভিত্তি করে একটি গণনা! আমি কেবল দ্বিতীয় পদ্ধতির ভি ভ্যালু করবো বলে আশা করতাম; রিটার্ন ডিক্ট্রি। ট্রাইগেটভ্যালু (কী, আউট মান)? মান: ডিফল;
জন কুম্বস

1
@ জ্যাকউম্বস ডানদিকে, তৃতীয় ওভারলোড একই উদ্দেশ্যে রয়েছে। এবং হ্যাঁ আপনি দ্বিতীয় ওভারলোডে এটি করতে পারেন তবে আমি এটি কিছুটা শুকিয়ে যাচ্ছিলাম (যাতে আমি যুক্তির পুনরাবৃত্তি করি না)।
নওফাল

4
@ নওফাল ভাল পয়েন্ট। শুকনো থাকা একটি ম্যাসিলে মেথড কল এড়ানো থেকে গুরুত্বপূর্ণ।
জন কমবস

19

কেউ .net কোর 2 এবং উপরে (গ # 7.x) ব্যবহার করে থাকেন, তাহলে CollectionExtensions বর্গ চালু করা হয় এবং ব্যবহার করতে পারেন GetValueOrDefault পদ্ধতি যদি চাবি অভিধানে নেই ডিফল্ট মান জন্য।

Dictionary<string, string> colorData = new  Dictionary<string, string>();
string color = colorData.GetValueOrDefault("colorId", string.Empty);

4

Collections.Specialized.StringDictionaryঅনুপস্থিত কীটির মান সন্ধান করার সময় একটি ব্যতিক্রম ব্যতীত ফলাফল সরবরাহ করে। এটি ডিফল্ট ক্ষেত্রে কেস-সংবেদনশীলও।

আদেশ সহকারে

এটি কেবল তার বিশেষায়িত ব্যবহারের জন্য বৈধ, এবং - জেনেরিকের আগে ডিজাইন করা হয়েছে - আপনার যদি পুরো সংগ্রহটি পর্যালোচনা করতে হয় তবে এর খুব ভাল গণক নেই।


4

আপনি যদি নেট কোর ব্যবহার করছেন তবে আপনি সংগ্রহের এক্সটেনশনগুলি ব্যবহার করতে পারেন et গেটভ্যালুঅর ডিফল্ট পদ্ধতি। এটি গ্রহণযোগ্য উত্তরে প্রদত্ত বাস্তবায়ন হিসাবে একই।

public static TValue GetValueOrDefault<TKey,TValue> (
   this System.Collections.Generic.IReadOnlyDictionary<TKey,TValue> dictionary,
   TKey key);

3
public class DefaultIndexerDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    private IDictionary<TKey, TValue> _dict = new Dictionary<TKey, TValue>();

    public TValue this[TKey key]
    {
        get
        {
            TValue val;
            if (!TryGetValue(key, out val))
                return default(TValue);
            return val;
        }

        set { _dict[key] = value; }
    }

    public ICollection<TKey> Keys => _dict.Keys;

    public ICollection<TValue> Values => _dict.Values;

    public int Count => _dict.Count;

    public bool IsReadOnly => _dict.IsReadOnly;

    public void Add(TKey key, TValue value)
    {
        _dict.Add(key, value);
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        _dict.Add(item);
    }

    public void Clear()
    {
        _dict.Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return _dict.Contains(item);
    }

    public bool ContainsKey(TKey key)
    {
        return _dict.ContainsKey(key);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        _dict.CopyTo(array, arrayIndex);
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _dict.GetEnumerator();
    }

    public bool Remove(TKey key)
    {
        return _dict.Remove(key);
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return _dict.Remove(item);
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return _dict.TryGetValue(key, out value);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _dict.GetEnumerator();
    }
}

1

অভিধানের কী-লুকিংয়ের জন্য একটি ইন্টারফেসটি সংজ্ঞায়িত করতে পারে। আমি সম্ভবত এটি কিছু হিসাবে সংজ্ঞায়িত করব:

Interface IKeyLookup(Of Out TValue)
  Function Contains(Key As Object)
  Function GetValueIfExists(Key As Object) As TValue
  Function GetValueIfExists(Key As Object, ByRef Succeeded As Boolean) As TValue
End Interface

Interface IKeyLookup(Of In TKey, Out TValue)
  Inherits IKeyLookup(Of Out TValue)
  Function Contains(Key As TKey)
  Function GetValue(Key As TKey) As TValue
  Function GetValueIfExists(Key As TKey) As TValue
  Function GetValueIfExists(Key As TKey, ByRef Succeeded As Boolean) As TValue
End Interface

নন-জেনেরিক কী সহ সংস্করণটি নন-স্ট্রাকচার কী প্রকারগুলি ব্যবহার করে কোডটি স্বেচ্ছাসেবক কী প্রকরণের জন্য অনুমতি দেয় যা জেনেরিক ধরণের পরামিতি দিয়ে সম্ভব নয়। যেহেতু পরেরটির অনুমতি দেয় সেহেতু একজনকে মিউটেবল Dictionary(Of Cat, String)হিসাবে পরিবর্তনীয় হিসাবে ব্যবহার করার অনুমতি দেওয়া উচিত নয় । তবে একটি পরিবর্তনীয় হিসাবে পরিবর্তনীয় হিসাবে ব্যবহার করার ক্ষেত্রে কোনও ভুল নেই , যেহেতু একটি নিখুঁতভাবে সুগঠিত অভিব্যক্তি হিসাবে বিবেচনা করা উচিত (এটি অভিধানে অনুসন্ধান না করেই ফিরে আসবে , টাইপ নয় এমন কিছু জন্যDictionary(Of Animal, String)SomeDictionaryOfCat.Add(FionaTheFish, "Fiona")Dictionary(Of Cat, String)Dictionary(Of Animal, String)SomeDictionaryOfCat.Contains(FionaTheFish)falseCat )।

দুর্ভাগ্যক্রমে, কেবলমাত্র এই জাতীয় ইন্টারফেসটি ব্যবহার করতে সক্ষম হওয়ার একমাত্র উপায় হ'ল যদি Dictionaryকোনও ক্লাসে কোনও বস্তু আবৃত করে যা ইন্টারফেস প্রয়োগ করে। আপনি যা করছেন তার উপর নির্ভর করে তবে এই জাতীয় ইন্টারফেস এবং এটির বৈকল্পিকতা এটির পক্ষে প্রচেষ্টাটিকে উপযুক্ত করে তুলতে পারে।


1

আপনি যদি এএসপি.এনইটি এমভিসি ব্যবহার করে থাকেন তবে আপনি কাজটি করে এমন রুটভ্যালিউড অভিধান অভিধান শ্রেণি অর্জন করতে পারেন।

public object this[string key]
{
  get
  {
    object obj;
    this.TryGetValue(key, out obj);
    return obj;
  }
  set
  {
    this._dictionary[key] = value;
  }
}

1

এই প্রশ্নটি নিশ্চিত করেছে যে TryGetValueনাটকগুলি অভিনয় করেFirstOrDefault এখানে ভূমিকা পালন করে।

একটি আকর্ষণীয় সি # 7 বৈশিষ্ট্যটি আমি উল্লেখ করতে চাই তা হল আউট ভেরিয়েবল বৈশিষ্ট্য এবং আপনি যদি সি # 6 থেকে নাল-কন্ডিশনাল অপারেটরটিকে সমীকরণের সাথে যুক্ত করেন তবে অতিরিক্ত কোড এক্সটেনশন পদ্ধতির কোনও প্রয়োজন নেই আপনার কোডটি আরও সহজ হতে পারে।

var dic = new Dictionary<string, MyClass>();
dic.TryGetValue("Test", out var item);
item?.DoSomething();

এর নেতিবাচক দিকটি হ'ল আপনি এই জাতীয় ইনলাইন সবকিছু করতে পারবেন না;

dic.TryGetValue("Test", out var item)?.DoSomething();

আমাদের যদি এটি প্রয়োজন / করতে চাই তবে আমাদের উচিত জনের মতো একটি সম্প্রসারণ পদ্ধতি কোড করা উচিত।


1

সি # 7.1 এর বিশ্বের জন্য এখানে @ জোনস্কিটের একটি সংস্করণ রয়েছে যা একটি defaultচ্ছিক ডিফল্টকে পাস করার অনুমতি দেয়:

public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV defaultValue = default) => dict.TryGetValue(key, out TV value) ? value : defaultValue;

আপনি যেখানে ফিরে যেতে চান সেই ক্ষেত্রে অনুকূলকরণের জন্য দুটি ফাংশন থাকা আরও দক্ষ হতে পারে default(TV):

public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV defaultValue) => dict.TryGetValue(key, out TV value) ? value : defaultValue;
public static TV GetValueOrDefault2<TK, TV>(this IDictionary<TK, TV> dict, TK key) {
    dict.TryGetValue(key, out TV value);
    return value;
}

দুর্ভাগ্যক্রমে সি # এর কমা অপারেটর নেই (বা সি # 6 প্রস্তাবিত সেমিকোলন অপারেটর) যাতে আপনার একটি ওভারলোডের জন্য একটি আসল ফাংশন বডি (হাঁপা!) থাকতে হবে।


1

আপনারা যারা সি ++ এর সাথে পরিচিত তাদের জন্য আমি একটি এসটিএল মানচিত্রের মতো আচরণের সাথে একটি আইডিকোরিয়ালি তৈরি করতে এনক্যাপসুলেশন ব্যবহার করেছি । যারা নেই তাদের জন্য:

  • সূচক নীচের সেফড অভিধানে {get পান কোনও কী উপস্থিত না থাকলে ডিফল্ট মান প্রদান করে এবং সেই কীটি একটি ডিফল্ট মান সহ অভিধানে যোগ করে। এটি প্রায়শই পছন্দসই আচরণ, কারণ আপনি এমন আইটেম সন্ধান করছেন যা শেষ পর্যন্ত প্রদর্শিত হবে বা প্রদর্শিত হওয়ার ভাল সুযোগ থাকবে।
  • পদ্ধতি অ্যাড (টি কে কী, টিভি ভাল) একটি অ্যাডআরআপডেট পদ্ধতি হিসাবে আচরণ করে, উপস্থিত মানটি নিক্ষেপের পরিবর্তে উপস্থিত থাকলে প্রতিস্থাপন করে। আমি কেন দেখতে পাচ্ছি না কেন মি an এর একটি অ্যাডআরআপডেট পদ্ধতি নেই এবং খুব সাধারণ পরিস্থিতিতে ত্রুটি নিক্ষেপ করা ভাল ধারণা বলে আমি মনে করি।

টিএল / ডিআর - নিরাপদ অভিধানটি এমনভাবে লেখা হয় যাতে কখনও বিকৃত পরিস্থিতি ব্যতীত কোনও পরিস্থিতিতে ব্যতিক্রম না ছুঁতে পারে , যেমন যেমন কম্পিউটার স্মৃতি থেকে বেরিয়ে আসে (বা আগুনে থাকে)এটি AddOrUpdate আচরণের সাথে অ্যাডকে প্রতিস্থাপন করে এবং সূচক থেকে নটফাউন্ডএক্সসেপশন নিক্ষেপের পরিবর্তে ডিফল্ট ফিরে আসে।

কোডটি এখানে:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class SafeDictionary<TK, TD>: IDictionary<TK, TD> {
    Dictionary<TK, TD> _underlying = new Dictionary<TK, TD>();
    public ICollection<TK> Keys => _underlying.Keys;
    public ICollection<TD> Values => _underlying.Values;
    public int Count => _underlying.Count;
    public bool IsReadOnly => false;

    public TD this[TK index] {
        get {
            TD data;
            if (_underlying.TryGetValue(index, out data)) {
                return data;
            }
            _underlying[index] = default(TD);
            return default(TD);
        }
        set {
            _underlying[index] = value;
        }
    }

    public void CopyTo(KeyValuePair<TK, TD>[] array, int arrayIndex) {
        Array.Copy(_underlying.ToArray(), 0, array, arrayIndex,
            Math.Min(array.Length - arrayIndex, _underlying.Count));
    }


    public void Add(TK key, TD value) {
        _underlying[key] = value;
    }

    public void Add(KeyValuePair<TK, TD> item) {
        _underlying[item.Key] = item.Value;
    }

    public void Clear() {
        _underlying.Clear();
    }

    public bool Contains(KeyValuePair<TK, TD> item) {
        return _underlying.Contains(item);
    }

    public bool ContainsKey(TK key) {
        return _underlying.ContainsKey(key);
    }

    public IEnumerator<KeyValuePair<TK, TD>> GetEnumerator() {
        return _underlying.GetEnumerator();
    }

    public bool Remove(TK key) {
        return _underlying.Remove(key);
    }

    public bool Remove(KeyValuePair<TK, TD> item) {
        return _underlying.Remove(item.Key);
    }

    public bool TryGetValue(TK key, out TD value) {
        return _underlying.TryGetValue(key, out value);
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return _underlying.GetEnumerator();
    }
}


0

এই ওয়ান-লাইনার সম্পর্কে কী যা কোনও কী ব্যবহার করে উপস্থিত রয়েছে কিনা তা পরীক্ষা করে ContainsKeyএবং তারপরে শর্তসাপেক্ষ অপারেটরটি ব্যবহার করে স্বাভাবিকভাবে পুনরুদ্ধারকৃত মান বা ডিফল্ট মানটি দেয়?

var myValue = myDictionary.ContainsKey(myKey) ? myDictionary[myKey] : myDefaultValue;

ডিফল্ট মানগুলিকে সমর্থন করে এমন একটি নতুন অভিধান শ্রেণি প্রয়োগ করার দরকার নেই, কেবলমাত্র উপরে আপনার উপরের সংক্ষিপ্ত লাইনের সাথে আপনার অনুসন্ধানের বিবৃতিগুলি প্রতিস্থাপন করুন।


5
এটির পরিবর্তে এটির পরিবর্তে দুটি অনুসন্ধান রয়েছে এবং আপনি যদি কনকন্টারডিয়েশনারি ব্যবহার করছেন তবে এটি একটি রেসের শর্তটি প্রবর্তন করে।
পিয়াদার

0

এটি TryGetValueযদি হয় তবে এটি ডিফল্ট মানটি পরীক্ষা করে ফেরত দিতে ওয়ান-লাইনার হতে পারে false

 Dictionary<string, int> myDic = new Dictionary<string, int>() { { "One", 1 }, { "Four", 4} };
 string myKey = "One"
 int value = myDic.TryGetValue(myKey, out value) ? value : 100;

myKey = "One" => value = 1

myKey = "two" => value = 100

myKey = "Four" => value = 4

এটি অনলাইনে চেষ্টা করুন


-1

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


11
এটি হতে পারে - তবে কিছু পরিস্থিতিতে আপনি হয়ত জানেন যে এটি তা নয়। আমি কখনও কখনও এটি দরকারী হতে পারে।
জন স্কিটি

8
যদি আপনি জানেন যে শূন্যটি সেখানে নেই - এটি পেয়ে অত্যন্ত আনন্দিত। এটি
লিঙ্কে

1
কনটেনস্কি পদ্ধতি ব্যবহার করে?
ম্যাটড্যাভি

4
হ্যাঁ, এটি আসলে খুব দরকারী। পাইথনের এটি রয়েছে এবং আমি পাইথনটিতে থাকাকালীন প্লেইন পদ্ধতির চেয়ে অনেক বেশি ব্যবহার করি। যে বিবৃতিগুলি কেবল নালার ফলাফলের জন্য যাচাই করা হয় তা যদি প্রচুর পরিমাণে লেখা সংরক্ষণ করে। (আপনি ঠিক বলেছেন, অবশ্যই, সেই নালটি মাঝেমধ্যে দরকারী, তবে সাধারণত আমি পরিবর্তে "" বা 0 চাইছি
Jon

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