IT-Swarm.Net

एक शब्दकोश पर पुनरावृति करने का सबसे अच्छा तरीका क्या है?

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

2249
Jake Stewart
foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}
3260
Pablo Fernandez

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

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 कीवर्ड वैकल्पिक C # 3.0 और ऊपर की विशेषता है, आप यहां अपनी कुंजी/मान के सटीक प्रकार का उपयोग भी कर सकते हैं)

743
Jacob

कुछ मामलों में आपको एक काउंटर की आवश्यकता हो सकती है जो लूप कार्यान्वयन के लिए प्रदान किया जा सकता है। उसके लिए, LINQ प्रदान करता है ElementAt जो निम्नलिखित को सक्षम करता है:

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}
124
Maurício Fedatto

निर्भर करता है कि आप कुंजियों या मूल्यों के बाद हैं ...

MSDN 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);
}
82
J Healy

आम तौर पर, एक विशिष्ट संदर्भ के बिना "सबसे अच्छा तरीका" के लिए पूछना यह पूछने के समान है कि सबसे अच्छा रंग क्या है।.

एक हाथ, कई रंग हैं और कोई सबसे अच्छा रंग नहीं है। यह जरूरत पर निर्भर करता है और अक्सर स्वाद पर भी।.

दूसरी ओर, C # में एक शब्दकोश पर पुनरावृति करने के कई तरीके हैं और कोई सबसे अच्छा तरीका नहीं है। यह जरूरत पर निर्भर करता है और अक्सर स्वाद पर भी।.

सबसे सीधा रास्ता है

foreach (var kvp in items)
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

यदि आपको केवल मान की आवश्यकता है (इसे item कहने की अनुमति है, kvp.Value से अधिक पठनीय है)।.

foreach (var item in items.Values)
{
    doStuff(item)
}

यदि आपको एक विशिष्ट प्रकार के आदेश की आवश्यकता है

आम तौर पर, शुरुआती एक शब्दकोश की गणना के आदेश के बारे में हैरान होते हैं।.

LINQ एक संक्षिप्त सिंटैक्स प्रदान करता है जो ऑर्डर (और कई अन्य चीजों) को निर्दिष्ट करने की अनुमति देता है, उदा .:

foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

फिर आपको केवल मूल्य की आवश्यकता हो सकती है। LINQ भी एक संक्षिप्त समाधान प्रदान करता है:

  • मूल्य पर सीधे iterate (इसे item को कॉल करने की अनुमति देता है, kvp.Value से अधिक पठनीय है)
  • लेकिन चाबियाँ द्वारा हल किया गया

यह रहा:

foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
    doStuff(item)
}

कई और वास्तविक दुनिया के उपयोग के मामले हैं जो आप इन उदाहरणों से कर सकते हैं। यदि आपको एक विशिष्ट आदेश की आवश्यकता नहीं है, तो बस "सबसे सीधा रास्ता" (ऊपर देखें) से चिपके रहें!

70
Stéphane Gourichon

मैं कहूंगा कि फॉर्च्यूनर मानक तरीका है, हालांकि यह स्पष्ट रूप से इस बात पर निर्भर करता है कि आप क्या खोज रहे हैं

foreach(var kvp in my_dictionary) {
  ...
}

कि तुम क्या देख रहे हो?

45
George Mauer

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

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

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

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

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

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

24
theo

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

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

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

शब्दकोशों को लुकअप के लिए ऑप्टिमाइज़ किया गया है, इसलिए इस बात को ध्यान में रखते हुए कि मैंने दो तरीके बनाए हैं। एक बस एक फॉर्च्यूनर करता है, दूसरा फिर कुंजियों को दिखाता है।.

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";
}

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

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

यहाँ RunTest तरीका है जो आपको यह देखने में मदद करता है कि क्या चल रहा है।.

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);
}

यहाँ सामान्य फ़ॉरेस्ट रन 0.2820564 सेकंड (लगभग दस गुना अधिक एक एकल पुनरावृत्ति से लिया - जैसा कि आप उम्मीद करेंगे) लिया। कुंजियों पर पुनरावृत्ति ने 2.2249449 सेकंड का समय लिया।.

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

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

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

C # 7.0 पेश Deconstructors और अगर आप .NET Core 2.0+ अनुप्रयोग का उपयोग कर रहे हैं, तो संरचना KeyValuePair<> में पहले से ही आपके लिए एक Deconstruct() शामिल है। तो आप कर सकते हैं:

var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}

 enter image description here

13
Jaider

आपने इसे पुनरावृति का सुझाव दिया है

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

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

FYI, foreach काम नहीं करता है अगर मूल्य प्रकार वस्तु के हैं।.

11
Khushi

.NET Framework 4.7 के साथ कोई भी उपयोग कर सकता है अपघटन

var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
    Console.WriteLine(fruit + ": " + number);
}

इस कोड को निचले C # संस्करणों पर काम करने के लिए, System.ValueTuple NuGet package जोड़ें और कहीं लिखें

public static class MyExtensions
{
    public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> Tuple,
        out T1 key, out T2 value)
    {
        key = Tuple.Key;
        value = Tuple.Value;
    }
}
10
Pavel

का उपयोग कर C # 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> के KeyValuePair को एक दृढ़ता से टाइप किए गए Tuple में बदल देती है, जिससे आप इस नए आरामदायक वाक्यविन्यास का उपयोग कर सकते हैं।.

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

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

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

इसे देखें: MSDN ब्लॉग - C # 7 में नई सुविधाएँ

8
sɐunıɔןɐqɐp

एक शब्दकोश को पुनरावृत्त करने के लिए सबसे सरल रूप:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}
8
Ron

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

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

6
ender

मैंने MSDN पर DictionaryBase वर्ग के लिए प्रलेखन में यह तरीका पाया:

foreach (DictionaryEntry de in myDictionary)
{
     //Do some stuff with de.Value or de.Key
}

यह एकमात्र ऐसा वर्ग था, जो डिक्शनबेस से विरासत में मिली कक्षा में सही ढंग से काम करने में सक्षम था।.

5
Zannjaminderson

C # 7 के अनुसार, आप ऑब्जेक्ट्स को वेरिएबल्स में डिक्रिप्ट कर सकते हैं। मेरा मानना ​​है कि यह एक शब्दकोश पर पुनरावृति करने का सबसे अच्छा तरीका है।.

उदाहरण:

KeyValuePair<TKey, TVal> पर एक विस्तार विधि बनाएँ जो इसे डिकंस्ट्रक्ट करता है:

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> पर Iterate करें

// 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}");
}
3
Domn Werner

MSDN पर आधिकारिक प्रलेखन के अनुसार, एक शब्दकोश पर पुनरावृति करने का मानक तरीका है:

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

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

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

यदि कहें, तो आप डिफ़ॉल्ट रूप से मान संग्रह पर चलना चाहते हैं, मेरा मानना ​​है कि आप IEnumerable <> को लागू कर सकते हैं, जहां टी शब्दकोश में मान ऑब्जेक्ट का प्रकार है, और "यह" एक शब्दकोश है।.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}
2
mzirino

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

    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }

इस तरह मैं इस तरह कोड लिख सकता हूं:

myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););
2
boca

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

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));
1
Steven Delrue
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

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

बस मेरा 2 प्रतिशत जोड़ना चाहते थे, क्योंकि अधिकांश उत्तर फॉरच-लूप से संबंधित थे। कृपया, निम्नलिखित कोड पर एक नज़र डालें:

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));
});

यह माना जाता है कि '.TLList ()' का एक अतिरिक्त कॉल आता है, इसमें थोड़ा सा प्रदर्शन-सुधार हो सकता है (जैसा कि यहां बताया गया है foreach vs someList.Foreach) () {} ), बड़े शब्दों के साथ काम करते हुए स्पष्ट रूप से और समानांतर में चलने का कोई विकल्प नहीं है/इसका असर बिल्कुल नहीं होगा।.

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

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

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

शब्दकोश <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);
}
0
Sheo Dayal Singh

शब्दकोश से अधिक तीन अलग तरीकों का उच्चारण।.

विधि 1-लूप के लिए उपयोग करना

for (int i = 0; i < DemotestDictionary.Count; i++ )
 {
 int key = i;
 string value = DemotestDictionary[i];
 // Do something here
 }

विधि 2-फ़ॉर्च इटरेशन का उपयोग करना

foreach (var entry in DemotestDictionary)
 {
 int key = entry.Key;
 string value = entry.Value;
 // Do something here
 } 

विधि 3-फ़ॉरवर्ड इटैरेशन का उपयोग करके KeyValuePair का उपयोग करें

foreach (KeyValuePair<int, string> entry in DemotestDictionary)
 {
 int key = entry.Key;
 string value = entry.Value;
// Do something here
 }
0
Sunil Dhappadhule