2010-08-31 16 views
7

इस कोड को अनुकूलित करने के लिए कैसे करें?foreach निकालें - सी # कोड-अनुकूलन

अभिभावक सूची, चाइल्डडॉगलिस्टिस - Ilist। dogListBox - सूची बॉक्स

foreach (Dog ParentDog in ParentDoglist) 
{ 
foreach (Dog ChildDog in ChildDoglist) 
{ 
    if(ParentDog.StatusID==ChildDog.StatusID) 
    dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 
} 
} 

संपादित करें: ParentDogTypeList, DogTypeList ParentDoglist, ChildDoglist, जहां दोनों एक दूसरे को

if(ParentDog.Key==ChildDog.Key) 

साथ संबंधित नहीं हैं

if(ParentDog.StatusID==ChildDog.StatusID) 
में बदल गया था के रूप में नाम दिया गया

पूर्ण कहानी:

मुझे एक ड्रॉप डाउन पॉप्युलेट करने की आवश्यकता है जो एक अभिभावक बाल संबंध का सहारा लेगा। ऐसे कुछ कुत्ते हैं जिनके पास कोई बच्चा नहीं हो सकता है और जिसे पत्ते के रूप में बुलाया जाएगा। और मैं भी

डीडी तरह

Parent1 
    Child11 (10) 
    Child12 (12) 
Parent2 
    Child21 (23) 
    Child22 (20) 
Leaf1 (20) 
Leaf2 (34) 

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

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

कोई पेरेंट किसी भी गिनती के लिए होता है, केवल बच्चे और पत्ती गिनती होता

तालिका स्कीमा:

alt text

+1

कौन सी लाइन धीमी है? –

+1

क्या DogType सभी कुत्ते के प्रकारों की एक सूची है और ParentDogTypeList कुत्ते के प्रकार का सबसेट है? – gkrogers

+0

@gkrogers Pl मेरे संपादन को देखें –

उत्तर

8

आप ParentDoglist और ChildDoglist सॉर्ट और रैखिक O(n) कर के एल्गोरिथ्म इनसीड खोजने सकते हैं यह O(n^2)

लेकिन आप O((ParentDoglist.Size() + ChildDoglist.Size()) * log2(ParentDoglist.Size() + ChildDoglist.Size())) में कंटेनर को सॉर्ट कर सकते हैं।

तो अगर आप इस कोड चलाने केवल एक बार, अपने एल्गोरिथ्म इष्टतम है। लेकिन यदि आप से अधिक समय खोज रहे हैं, तो इष्टतम समाधान कंटेनर को सॉर्ट करता है और रैखिक समय में तुलना करता है, लेकिन यदि आपका कंटेनर bettwen खोज फ़ंक्शन बदल सकता है और आप "एक से अधिक समय समाधान" का उपयोग कर रहे हैं इस तत्व को ले जाने के लिए RB-Tree कंटेनर का उपयोग करना चाहिए, क्योंकि कंटेनर के बाद सामान्य सूची के साथ आप O(log(n)) समय में क्रमबद्ध स्थिति में वापस नहीं आ सकते हैं।

-1
foreach (var ParentDog in ParentDoglist.Where(p=>ChildDoglist.Any(c=>c.Key== p.Key)).ToList()) 
    dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 

कैसे आप अपने सबसे बड़ी समस्या LinQ

+0

क्या अभी भी एक निहित नेस्टेड लूप नहीं है? –

+0

यह अभी भी ओ (एन^2) ;-(केवल किसी भी अनुकूलन के बिना चाइल्डडॉगलिस्ट कंटेनर में आलसी foreach के साथ। – Svisstack

2

साथ यह करना होगा है कि शायद dogListBox.Items.Add है। एक ही समय में प्रत्येक आइटम को जोड़ना काफी महंगा है। ListBox.Items.AddRange अधिक कुशल है।

आंतरिक लूप को बहुत छोटा बनाने के लिए आप आंतरिक लूप में कुंजियों के लिए एक लुकअप बना सकते हैं।

List<ListItem> listItems = new List<ListItem>(); 
ILookup<string, Dog> childDogsPerKey = ChildDoglist.ToLookup(dog => dog.Key); 
foreach (Dog ParentDog in ParentDoglist) 
{ 
    foreach (Dog ChildDog in childDogsPerKey[ParentDog.Key]) 
    { 
     listItems.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 
    } 
} 
dogListBox.Items.AddRange(listItems.ToArray()); 

यह कोड मानता है कि कई बाल कुत्तों की एक ही कुंजी हो सकती है। यदि प्रति कुंजी केवल एक बच्चा कुत्ता हो सकता है तो आप .ToDictionary() का उपयोग कर सकते हैं

+0

सहमत हैं कि AddRange शायद बहुत मदद करेगा। –

1

चूंकि यह डीबी से आ रहा है, इसलिए डेटाबेस राउंड ट्रिप एक प्रदर्शन हत्यारा होने की संभावना है। इसके अलावा तुलना ParentDog.Key==ChildDog.Key एसक्यूएल में किया जा सकता है, इसलिए आप इसे छोड़ने के लिए अपने सभी ऐप को उस डेटा को खींच नहीं सकते हैं।

इसे फिर से डिजाइन करें ताकि आप एक ही प्रश्न में सभी डेटा को पकड़ने के लिए एक ही चयन कर सकें।

अल्बिन ने AddRange का उल्लेख किया है, लेकिन आप इसे एक कदम आगे भी ले सकते हैं और अपने ग्रिड को वर्चुअलाइज कर सकते हैं ताकि वह ग्रिड के उस हिस्से को देखकर केवल उपयोगकर्ता को प्रदर्शित पंक्तियों को खींच सके।

संपादित

अपनी सूची ऐसा लगता है आप डीबी से कुछ इस तरह वापस जाने के लिए की जरूरत बनाने के लिए:

 
Parent1, null, null 
Parent1, Child1, 110 
Parent1, Child12, 12 
Parent2, null, null 
Parent2, Child21, 23 
Parent2, Child22 ,20 
Leaf1, null, 20 
Leaf2, null, 34 

यह लगता है कि आप left join किसी प्रकार का है और एक count की जरूरत है, एक साथ संभावित union all फेंक दिया गया।

+0

पूर्ण सागरियो –

+0

हां बिल्कुल समझाने के लिए मेरे प्रश्न को संपादित किया मैं किसी भी लूप के बिना सूची बॉक्स पॉप्युलेट? –

+0

@ एसआरआई, एक सिंगल क्वेरी और एक लूप, मैं अब टेबल स्कीमा और एसक्यूएल स्वाद के बिना एसक्यूएल स्वाद के बिना मदद नहीं कर सकता हूं (एसक्यूएल सर्वर मानते हैं) –

1

यह धीमा नहीं है, यह नई वस्तुओं को जोड़ रहा है और प्रस्तुत कर रहा है।

beginupdate जोड़ें/endupdate:

dogListBox.BeginUpdate(); 
foreach (Dog ParentDog in ParentDoglist) 
{ 
foreach (Dog ChildDog in ChildDoglist) 
{ 
    if(ParentDog.Key==ChildDog.Key) 
    dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 
} 
} 
dogListBox.EndUpdate(); 
2

मुझे अभी भी लगता सबसे खूबसूरत और अनुकूलित जिस तरह से यह करने के लिए Linq उपयोग करने के लिए है।

box.Items.AddRange(
    ParentDoglist.Where(p=>ChildDoglist.Any(c=>c.StatusID== p.StatusID)) 
    .Select(r=>new ListItem(r.StatusID, r.Name)).ToArray()); 

यह सब कुछ है और यह केवल एक पंक्ति है। यदि आप जुड़ना पसंद करते हैं, तो आप इसे उस क्वेरी के साथ कर सकते हैं।

box.Items.AddRange(
    ParentDoglist.Join(ChildDoglist, p => p.StatusID, c => c.StatusID, (p,c)=>p) 
    .Select(r=>new ListItem(r.StatusID, r.Name)).ToArray()); 
0

आप नेस्टेड फ़ोरैच लूप को एक साधारण लिंक अभिव्यक्ति के साथ प्रतिस्थापित कर सकते हैं। इस काम के लिए आपको System.Linq का उपयोग करने की आवश्यकता है;

foreach (Dog ParentDog in 
      (from dog in ParentDogList 
      from ChildDog in dog.StatusId 
      where dog.StatusId == ChildDog.StatusId) 
      select dog)) 
{ 
    dogListBox.Items.Add(new ListItem(ParentDog.Name, ParentDog.Key)); 
}