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


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


1949
2017-09-26 18:20


मूल


मुझे आश्चर्य है कि इस प्रश्न के कई जवाब हैं, साथ ही साथ 923 बार एक अपरिवर्तित .. (फोरैच का उपयोग करता है) .. मैं बहस करता हूं, या कम से कम यह जोड़ता हूं कि अगर आपको एक शब्दकोश में फिर से शुरू करना है, तो संभावना है कि आप हैं इसे गलत तरीके से / अनुपयुक्त तरीके से उपयोग करना .. मुझे यह टिप्पणी करना पड़ा, क्योंकि मैंने उन तरीकों से दुर्व्यवहार किया जा रहा है जो आईएमएचओ उचित नहीं थे ... हां, दुर्लभ परिस्थितियां हो सकती हैं जब आप खोज के बजाए शब्दकोश को फिर से शुरू करते हैं, जो कि है यह इसके लिए डिज़ाइन किया गया है .. कृपया एक शब्दकोष पर पुनरावृत्ति करने के बारे में सोचने से पहले, इसे ध्यान में रखें। - Vikas Gupta
@ विकसगुप्त आप कुंजी-मूल्य जोड़े के संग्रह के साथ कुछ करने के लिए क्या सुझाव देंगे जब आप नहीं जानते कि चाबियाँ क्या होने जा रही हैं? - nasch
@nasch: myDictionary.Keys आपको एक संग्रह जिसमें कुंजी शामिल होगी myDictionary। - displayName
@displayName यदि आप प्रत्येक कुंजी-मूल्य जोड़ी के साथ कुछ करना चाहते हैं लेकिन मानों को देखने के लिए उपयोग करने के लिए कुंजी का संदर्भ नहीं है, तो आप शब्दकोश को फिर से चालू करेंगे, है ना? मैं बस यह इंगित कर रहा था कि विकास के दावों के बावजूद आप ऐसा करना चाहते हैं, यह आमतौर पर गलत उपयोग होता है। - nasch
यह कहने के लिए कि इसका गलत उपयोग यह दर्शाता है कि एक बेहतर विकल्प है। वह विकल्प क्या है? - Kyle Delaney


जवाब:


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

2901
2017-09-26 18:22



अगर मुझे वास्तव में शब्दकोश में कुंजी / मूल्य के प्रकार की जानकारी नहीं है तो क्या होगा। का उपयोग करते हुए var entry उस मामले में बेहतर है, और इस प्रकार मैंने वोट दिया यह जवाब उपर्युक्त के बजाय एक दूसरे देखो पर। - Ozair Kafray
@OzairKafray का उपयोग कर var जब आप नहीं जानते कि आमतौर पर प्रकार का बुरा अभ्यास होता है। - Nate
यह उत्तर बेहतर है क्योंकि पाब्लो आलसी कोडर "var" उपयोग के लिए डिफ़ॉल्ट नहीं था जो रिटर्न प्रकार को खराब करता है। - MonkeyWrench
@MonkeyWrench: मेह। विजुअल स्टूडियो जानता है कि प्रकार क्या है; आपको बस इतना करना है कि वे खोजने के लिए चर पर होवर करें। - Robert Harvey♦
जैसा मुझे समझ में आया, var केवल तभी काम करता है जब संकलन समय पर प्रकार ज्ञात हो। यदि विजुअल स्टूडियो इस प्रकार को जानता है तो यह आपके लिए भी उपलब्ध है। - Kyle Delaney


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

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 और ऊपर की सुविधा है, आप यहां अपनी चाबियों / मानों के सटीक प्रकार का भी उपयोग कर सकते हैं)


646
2017-09-26 18:22



आपके पहले कोड ब्लॉक के लिए var सुविधा सबसे आवश्यक है :) - nawfal
मैं सराहना करता हूं कि यह उत्तर बताता है कि आप कुंजी या मूल्यों को स्पष्ट रूप से पुन: सक्रिय कर सकते हैं। - Rotsiser Mho
मुझे यहां var के उपयोग पसंद नहीं है। यह देखते हुए कि यह सिर्फ वाक्य रचनात्मक चीनी है, इसका उपयोग क्यों करें? जब कोई कोड पढ़ने की कोशिश कर रहा है, तो उसे टाइप करने के लिए कोड के चारों ओर कूदना होगा myDictionary (जब तक वह निश्चित रूप से वास्तविक नाम नहीं है)। मुझे लगता है कि जब प्रकार स्पष्ट है तो var का उपयोग करना अच्छा होता है उदा। var x = "some string" लेकिन जब यह तुरंत स्पष्ट नहीं होता है तो मुझे लगता है कि यह आलसी कोडिंग है जो कोड रीडर / समीक्षक को दर्द देती है - James Wierzba
var मेरी राय में, कम से कम इस्तेमाल किया जाना चाहिए। विशेष रूप से, यह रचनात्मक नहीं है: प्रकार KeyValuePair संभवतः प्रश्न के लिए प्रासंगिक है। - Sinjai


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

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

107
2018-03-10 20:44



'ElementAt 'विधि का उपयोग करने के लिए, याद रखें: System.Linq का उपयोग करना; यह एफएक्स में शामिल नहीं है। ऑटो जेनरेट टेस्ट कक्षाएं। - Tinia
यदि आप चाबियों से जुड़े मानों को संशोधित कर रहे हैं तो यह तरीका है। अन्यथा foreach () को संशोधित और उपयोग करते समय एक अपवाद फेंक दिया जाता है। - Mike de Klerk
इसका उपयोग करते समय सावधान रहें। यहाँ देखें: stackoverflow.com/a/2254480/253938 - RenniePet
नहीं है ElementAt एक ओ (एन) ऑपरेशन? - Arturo Torres Sánchez
यह जवाब इतने सारे अपवर्तकों के पूरी तरह से अयोग्य है। एक शब्दकोश का कोई अंतर्निहित आदेश नहीं है, इसलिए इसका उपयोग करना .ElementAt इस संदर्भ में सूक्ष्म बग का कारण बन सकता है। ऊपर आर्टूरो का मुद्दा बहुत गंभीर है। आप शब्दकोश को फिर से शुरू करेंगे dictionary.Count + 1 ऐसे समय के लिए ओ (एन ^ 2) जटिलता की ओर अग्रसर होता है जो केवल ओ (एन) होना चाहिए। यदि आपको वास्तव में एक अनुक्रमणिका की आवश्यकता है (यदि आप करते हैं, तो आप शायद पहले स्थान पर गलत संग्रह प्रकार का उपयोग कर रहे हैं), आपको फिर से चलना चाहिए dictionary.Select( (kvp, idx) => new {Index = idx, kvp.Key, kvp.Value}) इसके बजाय और उपयोग नहीं करते हैं .ElementAt लूप के अंदर। - spender


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

एमएसडीएन से 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);
}

75
2017-09-26 18:27





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

एक तरफ, कई रंग हैं और कोई सर्वश्रेष्ठ रंग नहीं है। यह आवश्यकता पर निर्भर करता है और अक्सर स्वाद पर भी निर्भर करता है।

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

सबसे सरल तरीका

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 भी एक संक्षिप्त समाधान प्रदान करता है:

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

यह रहा:

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

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


55
2017-08-10 11:15



अंतिम होना चाहिए .Values और एक चयनित खंड नहीं है। - Mafii
@ माफी क्या आप निश्चित हैं? ऑर्डरबी द्वारा लौटाए गए मान एक KeyValuePair प्रकार के नहीं हैं, उनके पास नहीं है Value खेत। सटीक प्रकार मैं यहां देखता हूं IOrderedEnumerable<KeyValuePair<TKey, TValue>>। शायद आप कुछ और मतलब था? क्या आप एक पूर्ण रेखा लिख ​​सकते हैं जो दिखा रहा है कि आपका क्या मतलब है (और इसका परीक्षण करें)? - Stéphane Gourichon
मुझे लगता है कि इस जवाब में मेरा मतलब है: stackoverflow.com/a/141105/5962841 लेकिन अगर मैं कुछ उलझन में हूं तो मुझे सही करें - Mafii
@ माफि मेरे पूरे उत्तर को दोबारा पढ़ें, कोड खंडों के बीच स्पष्टीकरण संदर्भ बताते हैं। आपके द्वारा उल्लिखित उत्तर मेरे उत्तर में दूसरे कोड अनुभाग की तरह है (कोई ऑर्डर आवश्यक नहीं है)। वहां मैंने अभी लिखा था items.Value जैसा आपने सुझाव दिया था। आपके द्वारा टिप्पणी किए गए चौथे खंड के मामले में, Select() कारण बनने का एक तरीका है foreach कुंजी-मूल्य जोड़े के बजाय शब्दकोश में मूल्यों पर सीधे गणना करने के लिए। अगर किसी तरह आपको पसंद नहीं है Select()इस मामले में, आप तीसरे कोड खंड को प्राथमिकता दे सकते हैं। चौथे खंड का बिंदु यह दिखाने के लिए है कि कोई LINQ के साथ संग्रह को पूर्व-संसाधित कर सकता है। - Stéphane Gourichon
यदि तुम करो .Keys.Orderby() आप चाबियों की एक सूची पर फिर से शुरू करेंगे। अगर आपको बस इतना ही चाहिए, ठीक है। यदि आपको मानों की आवश्यकता है, तो लूप में आपको मूल्य प्राप्त करने के लिए प्रत्येक कुंजी पर शब्दकोश को क्वेरी करना होगा। कई परिदृश्यों में यह व्यावहारिक अंतर नहीं करेगा। उच्च प्रदर्शन परिदृश्य में, यह होगा। जैसा कि मैंने उत्तर की शुरुआत में लिखा था: "कई तरीके हैं (...) और कोई अच्छा तरीका नहीं है। यह आवश्यकता पर निर्भर करता है और अक्सर स्वाद पर भी निर्भर करता है।" - Stéphane Gourichon


मैं कहूंगा कि foreach मानक तरीका है, हालांकि यह स्पष्ट रूप से उस पर निर्भर करता है जो आप खोज रहे हैं

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

क्या आप यही खोज रहे हैं?


36
2017-09-26 18:22



उम, आइटम "मूल्य" नामकरण के बजाय नामकरण नहीं कर रहा है? आप आम तौर पर "value.Key" और "value.Value" जैसे सिंटैक्स का उपयोग करेंगे, जो किसी और के लिए बहुत सहज नहीं है जो कोड पढ़ रहे होंगे, खासकर यदि वे इस बात से परिचित नहीं हैं कि .Net Dictionary को कैसे कार्यान्वित किया गया है । - RenniePet
@RenniePet kvp आमतौर पर शब्दकोशों और संबंधित डेटा संरचनाओं पर पुनरावृत्ति करते समय KeyValuePair उदाहरणों का नाम देने के लिए प्रयोग किया जाता है: foreach(var kvp in myDictionary){...। - mbx


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

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

28
2018-06-11 13:32



@WiiMaxx और अधिक महत्वपूर्ण यदि ये आइटम एक-दूसरे पर निर्भर नहीं हैं - Mafii


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

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

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

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


22
2017-09-26 18:22





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

किसी सरणी की तरह किसी चीज़ पर पुनरावर्तित होने की तुलना में एक शब्दकोश पर इटरेट करना धीमा हो सकता है। मेरे परीक्षणों में एक सरणी पर एक पुनरावृत्ति 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 विधि का उपयोग करने से बहुत खराब कर सकते हैं।

22
2017-07-30 10:54



आपको डेटटाइम की बजाय स्टॉपवॉच जैसे कुछ उपाय करना चाहिए: hanselman.com/blog/... - Even Mien
क्या आप कृपया अपने परीक्षण परिदृश्य का वर्णन कर सकते हैं, आपके शब्दकोश में कितने आइटम, औसत समय की गणना करने के लिए आपने कितनी बार अपना परिदृश्य चलाया ... - WiiMaxx
दिलचस्प बात यह है कि शब्दकोश में आपके पास मौजूद डेटा के आधार पर आपको अलग-अलग परिणाम मिलेंगे। डिक्शनरी पर इटरेट करने के दौरान, एन्युमरेटर फ़ंक्शन को डिक्शनरी में बहुत सारे खाली स्लॉट छोड़ना पड़ता है, जो कि सरणी को फिर से चलाने से धीमा होने का कारण बनता है। यदि शब्दकोश भर गया है तो यह खाली खाली स्लॉट होगा यदि यह आधे खाली है। - Martin Brown


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

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 यदि मूल्य ऑब्जेक्ट के प्रकार हैं तो काम नहीं करता है।


9
2017-10-28 20:49



कृपया विस्तार से बताएं: foreach अगर काम नहीं करेगा कौन कौन से मूल्य प्रकार का है object? अन्यथा यह ज्यादा समझ में नहीं आता है। - Marc L.