2010-05-14 17 views
5

यह प्रश्न LINQ group one type of item जैसा है लेकिन एक अधिक सामान्य तरीके से संभाला जाता है।LINQ - समूह विशिष्ट प्रकार के वर्ग

मेरे पास एक सूची है जिसमें विभिन्न व्युत्पन्न कक्षाएं हैं। मैं इतना है कि प्राकृतिक व्यवस्था जो base.GroupThisType == सच है कुछ वर्गों के लिए छोड़कर बनाए रखा है LINQ अर्द्ध तरह करने के लिए सूची का उपयोग करने के कोशिश कर रहा हूँ

List<BaseClass> list = new List<BaseClass>() { 
    new Class1(1), 
    new Class2(1), 
    new Class1(2), 
    new Class3(1), 
    new Class2(2), 
    new Class4(1), 
    new Class3(2) 
}; 

: मैं कुछ इस तरह हो सकता है। GroupThisType वाले सभी वर्गों को उस स्थान पर एक साथ समूहीकृत किया जाना चाहिए कि उसी प्रकार की पहली श्रेणी होती है।

List<BaseClass> list = new List<BaseClass>() { 
    new Class1(1), 
    new Class1(2), 
    new Class2(1), 
    new Class3(1), 
    new Class3(2) 
    new Class2(2), 
    new Class4(1), 
}; 

संपादित करें:: यहाँ क्या उत्पादन किया जाना चाहिए की तरह है ओह, इस परिणाम यह सोचते है (Class1 और Class3) .GroupThisType == कहने के लिए भूल गया सच

+0

+1 यहां तक ​​कि अच्छे चुनौती – SLaks

+0

@SLaks: हाँ, केवल एक चीज मैं सोच रहा था GroupThisType दोहराया जाएगा और सिद्धांत में एक ही कक्षा की घटनाओं के लिए अलग-अलग हो सकता है। मैं एक सूची समूह TheseTypes बनाउंगा, लेकिन मुझे समय से पहले के प्रकार (प्लगइन-प्रकार सिस्टम) नहीं पता है। एक स्थैतिक चर शायद सबसे अधिक समझ में आता है। यह आपका जवाब नहीं बदलता है। –

+0

... सिवाय इसके कि अगर मैं इसे बेस क्लास में चाहता हूं तो मैं इसे स्थिर नहीं बना सकता, अन्यथा मेरे पास केवल उस चर का एक उदाहरण है। ओह ठीक है ... –

उत्तर

1

इस तरह:

list = list.Select((o, i) => new { Index = i * 10000, Value = o }) 
      .GroupBy(q => q.GetType()) 
      .SelectMany(g => { 
       if (g.First().GroupThisType) 
        return g.Select((q, i) => 
         new { Index = g.First().Index + i, Value = q.Value } 
        ); 
       else 
        return g; 
      }) 
      .OrderBy(q => q.Index) 
      .Select(q => q.Value) 
      .ToList(); 

i * 10000 एक समूह से 10,000 आइटम किसी भी दो आइटम के बीच सम्मिलित करने के लिए अप करने के लिए अनुमति देता है।

आप g.First().GroupThisTypetypesToGroup.Contains(g.Key) के साथ प्रतिस्थापित कर सकते हैं।

+0

मुझे लगता है कि एक और पारंपरिक दृष्टिकोण समझना आसान होगा :) इसके अलावा, मैं * 10000 करके आप सीमित कर रहे हैं कि कितने कुल आइटम हो सकते हैं। मुझे लगता है कि मैं एक int है, इसलिए 2147483647/10000 = 214748 अधिकतम आइटम। अभी भी मेरे पास क्या होगा। –

+0

'i' एक 'int' है, लेकिन आप इसे' long' पर डाल सकते हैं। – SLaks

0

OrderBy LINQ विधि स्वीकार कर सकते हैं एक आईसीओएमपेयर जेनेरिक इंटरफ़ेस। आप अपने कस्टम सॉर्टिंग एल्गोरिदम को लागू करने के लिए इसका उपयोग कर सकते हैं। मुझे नहीं पता कि डिफ़ॉल्ट ऑर्डरिंग आप जो करने की कोशिश कर रहे हैं उसे संभाल सकती है (यह उन सभी नियमों पर निर्भर करेगी जिन्हें आपको लागू करने की आवश्यकता है)। मुझे लगता है कि आप वर्गों को वास्तव में कक्षा 1, कक्षा 2 नाम के क्रम में आदेश के साथ नामित नहीं कर रहे हैं?

एचटीएच।

+1

वह मूल आदेश को संरक्षित करना चाहता है, लेकिन कुछ प्रकार के सभी वस्तुओं को पहली घटना की स्थिति में ले जाना चाहता है। 'IComparer' के साथ ऐसा करना संभव नहीं है। – SLaks

1

यहां दो पास का उपयोग करके एक समाधान है: सबसे पहले मैं समूह के सभी लोगों का एक शब्दकोश बना सकता हूं। दूसरे में मैं उन तत्वों को इकट्ठा करने के लिए SelectMany का उपयोग करता हूं जो कोलेट के किसी भी तत्व के पहले के लिए कोलेटेड अनुक्रमों के साथ मेल नहीं खाते हैं।

// Build a dictionary of the items that group 
var onesToGroup = list.Where(x => x.GroupThisClass) 
          .GroupBy(x => x.GetType()) 
          .ToDictionary(x => x.Key, x => x.AsEnumerable()); 

var results = list.SelectMany(x => x.GroupThisClass ? 
          (onesToGroup[x.GetType()].First() == x ? onesToGroup[x.GetType()] : (new BaseClass[]{})) 
               : (new []{x})); 
+0

लेकिन यह होगा, मैं शब्दकोश पर पुनरावृत्ति नहीं कर रहा हूं, मैं मूल सूची में पुनरावृत्ति कर रहा हूं और केवल प्रासंगिक समूह को खोजने के लिए शब्दकोश का उपयोग कर रहा हूं। –

+0

हाँ, आप सही हैं। मैंने गलत समझा। – SLaks

+0

हालांकि यह समूहबी पर निर्भर करता है ... जो कि सौभाग्य से एमएसडीएन पुष्टि करता है। –

संबंधित मुद्दे