c# - एक शब्दकोश पर फिर से शुरू करने का सबसे अच्छा तरीका क्या है?




dictionary loops (17)

मैंने सी # में एक शब्दकोश में फिर से शुरू करने के कुछ अलग तरीके देखे हैं। क्या कोई मानक तरीका है?

https://code.i-harness.com


आप मल्टीथ्रेड प्रोसेसिंग के लिए बड़े शब्दकोशों पर भी कोशिश कर सकते हैं।

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

आपने फिर से सुझाव देने के लिए सुझाव दिया है

Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary) {
    //Do some interesting things;
}

एफवाईआई, अगर मूल्य वस्तु के प्रकार हैं तो foreach काम नहीं करता है।


इस पर निर्भर करता है कि आप चाबियाँ या मूल्यों के बाद हैं ...

एमएसडीएन Dictionary(TKey, TValue) कक्षा विवरण:

// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}

// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;

// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;

// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}

उच्चतम रैंकिंग पदों के अलावा जहां उपयोग के बीच चर्चा है

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

या

foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

सबसे पूरा निम्नलिखित है क्योंकि आप प्रारंभिक से शब्दकोश प्रकार देख सकते हैं, केवीपी KeyValuePair है

var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x

foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}

एमएसडीएन पर आधिकारिक दस्तावेज के अनुसार, एक शब्दकोश पर फिर से शुरू करने का मानक तरीका है:

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}

कभी-कभी यदि आपको केवल मूल्यों की गणना करने की आवश्यकता होती है, तो शब्दकोश के मूल्य संग्रह का उपयोग करें:

foreach(var value in dictionary.Values)
{
    // do something with entry.Value only
}

इस पोस्ट द्वारा रिपोर्ट किया गया है जिसमें कहा गया है कि यह सबसे तेज़ तरीका है: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html


बस मेरा 2 प्रतिशत जोड़ना चाहता था, क्योंकि सबसे अधिक जवाब foreach-loop से संबंधित हैं। कृपया, निम्न कोड पर एक नज़र डालें:

Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();

//Add some entries to the dictionary

myProductPrices.ToList().ForEach(kvP => 
{
    kvP.Value *= 1.15;
    Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});

Altought यह 'टॉलिस्ट ()' का एक अतिरिक्त कॉल जोड़ता है, थोड़ा सा प्रदर्शन-सुधार हो सकता है (जैसा कि यहां बताया गया है कि कुछ शब्दकोशों के साथ foreach बनाम कुछ .istach () {} ), espacially जब बड़े शब्दकोश के साथ काम करते हैं और समानांतर में चल रहे हैं विकल्प / बिल्कुल असर नहीं होगा।

साथ ही, कृपया ध्यान दें कि आप foreach-loop के अंदर 'मान' प्रॉपर्टी को मान असाइन करने में सक्षम नहीं होंगे। दूसरी तरफ, आप 'कुंजी' में भी हस्तक्षेप करने में सक्षम होंगे, संभवतः आपको रनटाइम पर परेशानी हो रही है।

जब आप केवल कुंजी और मानों को "पढ़ना" चाहते हैं, तो आप IENumerable.Select () का भी उपयोग कर सकते हैं।

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );

बहुत सारे विकल्प हैं। मेरा निजी पसंदीदा KeyValuePair द्वारा है

Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}

आप कुंजी और मूल्य संग्रह का भी उपयोग कर सकते हैं


मैं .NET 4.0+ का लाभ उठाऊंगा और मूल रूप से स्वीकार किए गए एक को अद्यतन उत्तर प्रदान करूंगा:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}

मैं इस प्रश्न की सराहना करता हूं कि पहले से ही बहुत सारे प्रतिक्रियाएं हैं लेकिन मैं थोड़ा सा शोध करना चाहता हूं।

किसी सरणी की तरह किसी चीज़ पर पुनरावर्तित होने की तुलना में एक शब्दकोश पर इटरेट करना धीमा हो सकता है। मेरे परीक्षणों में एक सरणी पर एक पुनरावृत्ति 0.015003 सेकंड ले लिया गया जबकि एक शब्दकोश (एक ही संख्या में तत्वों के साथ) पर एक पुनरावृत्ति 0.0365073 सेकंड ले गया जो कि 2.4 गुना लंबा है! हालांकि मैंने बहुत बड़ा अंतर देखा है। तुलना के लिए एक सूची 0.00215043 सेकंड के बीच कहीं थी।

हालांकि, यह सेब और संतरे की तुलना की तरह है। मेरा मुद्दा यह है कि शब्दकोशों पर पुनरावृत्ति धीमी है।

शब्दकोश लुकअप के लिए अनुकूलित किए गए हैं, इसलिए इसे ध्यान में रखते हुए मैंने दो विधियां बनाई हैं। एक बस एक foreach करता है, दूसरा चाबियाँ फिर से दिखता है।

public static string Normal(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }

    return "Normal";
}

यह एक कुंजी को लोड करता है और इसके बजाय पुनरावृत्त करता है (मैंने चाबियों को स्ट्रिंग में खींचने का भी प्रयास किया [] लेकिन अंतर नगण्य था।

public static string Keys(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var key in dictionary.Keys)
    {
        value = dictionary[key];
        count++;
    }

    return "Keys";
}

इस उदाहरण के साथ सामान्य foreach परीक्षण 0.0310062 लिया और कुंजी संस्करण 0.2205441 लिया। सभी कुंजियों को लोड करना और सभी लुकअप पर पुनरावृत्ति स्पष्ट रूप से बहुत धीमी है!

अंतिम परीक्षण के लिए मैंने यह देखने के लिए दस बार अपना पुनरावृत्ति किया है कि क्या चाबियों का उपयोग करने के कोई लाभ हैं (इस बिंदु से मैं केवल उत्सुक था):

यहां रनटेस्ट विधि है यदि इससे आपको यह देखने में मदद मिलती है कि क्या हो रहा है।

private static string RunTest<T>(T dictionary, Func<T, string> function)
{            
    DateTime start = DateTime.Now;
    string name = null;
    for (int i = 0; i < 10; i++)
    {
        name = function(dictionary);
    }
    DateTime end = DateTime.Now;
    var duration = end.Subtract(start);
    return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
}

यहां सामान्य foreach रन 0.2820564 सेकंड (एक ही पुनरावृत्ति से लगभग दस गुना लंबा लिया - जैसा कि आप उम्मीद करेंगे)। चाबियों पर पुनरावृत्ति 2.224 9 44 9 सेकेंड ले लिया।

जोड़ने के लिए संपादित: कुछ अन्य उत्तरों को पढ़ने से मुझे सवाल आया कि अगर मैं शब्दकोश के बजाय शब्दकोश का उपयोग करता तो क्या होगा। इस उदाहरण में सरणी ने 0.0120024 सेकंड, सूची 0.0185037 सेकंड और शब्दकोश 0.04650 9 3 सेकंड लिया। यह अपेक्षा करना उचित है कि डेटा प्रकार इस बात पर एक फर्क पड़ता है कि शब्दकोश कितना धीमा है।

मेरे निष्कर्ष क्या हैं ?

  • यदि आप कर सकते हैं तो एक शब्दकोश पर पुनरावृत्ति से बचें, वे एक ही डेटा के साथ एक सरणी पर फिर से चलने से काफी धीमे हैं।
  • यदि आप एक शब्दकोश पर फिर से शुरू करना चुनते हैं तो बहुत चालाक होने की कोशिश न करें, हालांकि धीमी गति से आप मानक foreach विधि का उपयोग करने से बहुत खराब कर सकते हैं।

मैंने एक शब्दकोश पर लूप के लिए एक विस्तार लिखा था।

public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}

फिर आप कॉल कर सकते हैं

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));

यदि आप सी # में जेनेरिक डिक्शनरी का उपयोग करने की कोशिश कर रहे हैं, तो आप किसी अन्य भाषा में एक एसोसिएटिव सरणी का उपयोग करेंगे:

foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}

या, यदि आपको केवल चाबियों के संग्रह पर पुन: प्रयास करने की आवश्यकता है, तो उपयोग करें

foreach(var item in myDictionary.Keys)
{
  foo(item);
}

और आखिरकार, यदि आप केवल मूल्यों में रूचि रखते हैं:

foreach(var item in myDictionary.Values)
{
  foo(item);
}

(ध्यान दें कि var कीवर्ड एक वैकल्पिक सी # 3.0 और ऊपर की सुविधा है, आप यहां अपनी चाबियों / मानों के सटीक प्रकार का भी उपयोग कर सकते हैं)


शब्दकोश विशेष सूचियां हैं, जबकि सूची में प्रत्येक मान में एक कुंजी है जो एक चर भी है। एक शब्दकोश का एक अच्छा उदाहरण एक फोन बुक है।

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    phonebook.Add("Alex", 4154346543);
    phonebook["Jessica"] = 4159484588;

ध्यान दें कि एक शब्दकोश को परिभाषित करते समय, हमें दो प्रकार के साथ एक सामान्य परिभाषा प्रदान करने की आवश्यकता होती है - कुंजी का प्रकार और मूल्य का प्रकार। इस मामले में, कुंजी एक स्ट्रिंग है जबकि मान एक पूर्णांक है।

शब्दकोश में एकल मान जोड़ने के दो तरीके भी हैं, या तो ब्रैकेट ऑपरेटर का उपयोग कर या ऐड विधि का उपयोग कर।

यह जांचने के लिए कि क्या एक शब्दकोश में एक निश्चित कुंजी है, हम ContainsKey विधि का उपयोग कर सकते हैं:

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

if (phonebook.ContainsKey("Alex"))
{
    Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}

किसी शब्दकोश से किसी आइटम को निकालने के लिए, हम निकालें विधि का उपयोग कर सकते हैं। किसी कुंजी से अपनी कुंजी से किसी आइटम को निकालना तेज़ और बहुत ही कुशल है। किसी आइटम से अपने मूल्य का उपयोग करके किसी आइटम को हटाते समय, प्रक्रिया धीमी और अक्षम होती है, शब्दकोश निकालें फ़ंक्शन निकालें के विपरीत।

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);

सी # 7 के रूप में, आप वस्तुओं को चरों में विभाजित कर सकते हैं। मुझे विश्वास है कि यह एक शब्दकोश पर फिर से शुरू करने का सबसे अच्छा तरीका है।

उदाहरण:

KeyValuePair<TKey, TVal> पर एक एक्सटेंशन विधि बनाएं जो इसे deconstructs:

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey, out TVal val)
{
   key = pair.Key;
   val = pair.Value;
}

निम्नलिखित तरीके से किसी भी Dictionary<TKey, TVal>

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}

शब्दकोश <TKey, TValue> यह सी # में एक सामान्य संग्रह वर्ग है और यह डेटा को प्रमुख मान प्रारूप में संग्रहीत करता है। के लिए अद्वितीय होना चाहिए और यह शून्य नहीं हो सकता है जबकि मान डुप्लिकेट और शून्य हो सकता है। शब्दकोश में प्रत्येक आइटम जैसा है KeyValuePair <TKey, TValue> संरचना के रूप में माना जाता है जो एक कुंजी और उसके मूल्य का प्रतिनिधित्व करता है। और इसलिए हमें तत्व के पुनरावृत्ति के दौरान तत्व प्रकार KeyValuePair <TKey, TValue> लेना चाहिए। नीचे उदाहरण है।

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}

सी # 7 का उपयोग करके, इस समाधान विधि को अपने समाधान की किसी भी परियोजना में जोड़ें:

public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}


और इस सरल वाक्यविन्यास का उपयोग करें

foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


या यह एक, अगर आप पसंद करते हैं

foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


पारंपरिक जगह में

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


विस्तार विधि आपके IDictionary<TKey, TValue> दृढ़ता से टाइप किए गए tuple में की KeyValuePair को बदलती है, जिससे आप इस नए आरामदायक वाक्यविन्यास का उपयोग कर सकते हैं।

यह बदलता है- आवश्यक शब्दकोश प्रविष्टियों को टुपल्स में परिवर्तित करता है, इसलिए यह पूरे शब्दकोश को टुपल्स में परिवर्तित नहीं करता है, इसलिए उससे संबंधित कोई प्रदर्शन चिंता नहीं होती है।

KeyValuePair का उपयोग करने के साथ तुलना में एक tuple बनाने के लिए विस्तार विधि को कॉल करने वाली एकमात्र मामूली लागत है, जो कि यदि आप KeyValuePair की गुण Key और Value को नए लूप वैरिएबल को असाइन कर रहे हैं तो कोई समस्या नहीं होनी चाहिए।

व्यावहारिक रूप से, यह नया वाक्यविन्यास कम-स्तर वाले अल्ट्रा-उच्च प्रदर्शन परिदृश्यों को छोड़कर, अधिकांश मामलों के लिए बहुत अच्छी तरह से उपयुक्त है, जहां आपके पास अभी भी उस विशिष्ट स्थान पर इसका उपयोग करने का विकल्प नहीं है।

इसे देखें: एमएसडीएन ब्लॉग - सी # 7 में नई विशेषताएं


var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));






loops