LINQ:

2010-06-03 14 views
10

मैं दोहराया क्रमांक की एक सूची है प्रत्येक समूह में अधिकतम गिनती के साथ GroupByLINQ:

Enumerable.Range(1,3).Select(o => Enumerable.Repeat(o, 3)).SelectMany(o => o) 
    .GroupBy(o => o).Select(o => new { Qty = o.Count(), Num = o.Key }) 

Qty Num 
3  1 
3  2 
3  3 

क्या मैं सच में की जरूरत है सीमित करने के लिए है प्रति समूह मात्रा कुछ संख्या के लिए। अगर सीमा 2 है ऊपर समूह के लिए परिणाम होगा:

Qty Num 
2  1 
1  1 
2  2 
1  2 
2  3 
1  3 

तो, अगर मात्रा = 10 और सीमा 4 है, परिणाम 3 पंक्तियों है (4, 4, 2)। प्रत्येक संख्या की मात्रा उदाहरण के बराबर नहीं है। निर्दिष्ट मात्रा सीमा पूरी सूची के लिए समान है (संख्या के आधार पर भिन्न नहीं है)। , वहाँ कोई वास्तव में सुरुचिपूर्ण समाधान है और यह जब तक एसक्यूएल या इकाई की रूपरेखा के लिए Linq है (यानी एक SQL क्वेरी में अनुवाद किया जा रहा है) -

धन्यवाद

+0

मैं सिर्फ उत्सुक हूं। इस एल्गोरिदम के लिए क्या उपयोग किया जाता है? – Luke101

+0

मुझे सीएनसी मशीन के लिए इस प्रारूप में डेटा थूकना होगा। – JKJKJK

उत्तर

4

एक similar question कि आया था हाल ही में कैसे एसक्यूएल में यह करने के लिए पूछ रहा था मैं वास्तव में सुझाव दूंगा कि आप लिंक के साथ इस समस्या को हल करने का प्रयास करें और इसके बजाय एक पुनरावृत्त समाधान लिखें; यह बनाए रखने के लिए एक और अधिक कुशल और आसान हो जाएगा।

ने कहा है कि अगर आप पूरी तरह एक सेट के आधार पर ("Linq") विधि का उपयोग करना चाहिए, यह एक तरह से आप यह कर सकता है:

var grouped = 
    from n in nums 
    group n by n into g 
    select new { Num = g.Key, Qty = g.Count() }; 

int maxPerGroup = 2; 
var portioned = 
    from x in grouped 
    from i in Enumerable.Range(1, grouped.Max(g => g.Qty)) 
    where (x.Qty % maxPerGroup) == (i % maxPerGroup) 
    let tempQty = (x.Qty/maxPerGroup) == (i/maxPerGroup) ? 
     (x.Qty % maxPerGroup) : maxPerGroup 
    select new 
    { 
     Num = x.Num, 
     Qty = (tempQty > 0) ? tempQty : maxPerGroup 
    }; 

सरल और तेजी से पुनरावृत्ति संस्करण के साथ तुलना करें:

foreach (var g in grouped) 
{ 
    int remaining = g.Qty; 
    while (remaining > 0) 
    { 
     int allotted = Math.Min(remaining, maxPerGroup); 
     yield return new MyGroup(g.Num, allotted); 
     remaining -= allotted; 
    } 
} 
+0

आप LINQ विधि के बारे में बहुत जटिल हैं। धन्यवाद। – JKJKJK

0

हारून के उत्कृष्ट उत्तर में दोनों दुनिया के सर्वश्रेष्ठ होने की संभावना शामिल नहीं है ... एक पुनरावृत्ति समाधान प्रदान करने के लिए एक विस्तार विधि का उपयोग करना।

untested है:

public static IEnumerable<IEnumerable<U>> SplitByMax<T, U>(
    this IEnumerable<T> source, 
    int max, 
    Func<T, int> maxSelector, 
    Func<T, int, U> resultSelector 
) 
{ 
    foreach(T x in source) 
    { 
    int number = maxSelector(x); 
    List<U> result = new List<U>(); 
    do 
    { 
     int allotted = Math.Min(number, max); 
     result.Add(resultSelector(x, allotted)); 
     number -= allotted 
    } while (number > 0 && max > 0); 

    yield return result; 
    } 
} 

द्वारा कहा जाता है:

var query = grouped.SplitByMax(
    10, 
    o => o.Qty, 
    (o, i) => new {Num = o.Num, Qty = i} 
) 
.SelectMany(split => split); 
3

अन्य उत्तर में से कुछ LINQ क्वेरी कहीं अधिक जटिल की तुलना में यह करने की जरूरत है कर रहे हैं। foreach लूप का उपयोग करना निश्चित रूप से तेज़ और अधिक कुशल है, लेकिन LINQ विकल्प अभी भी काफी सरल है।

var input = Enumerable.Range(1, 3).SelectMany(x => Enumerable.Repeat(x, 10)); 
int limit = 4; 

var query = 
    input.GroupBy(x => x) 
     .SelectMany(g => g.Select((x, i) => new { Val = x, Grp = i/limit })) 
     .GroupBy(x => x, x => x.Val) 
     .Select(g => new { Qty = g.Count(), Num = g.Key.Val }); 
संबंधित मुद्दे

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