2010-08-18 20 views
17

क्या समूह का सबसे अच्छा तरीका n तत्वों प्रत्येक की सरणी की एक सूची में एक सरणी सी # में 4.प्रत्येक सरणी के समूह में किसी सरणी को कैसे विभाजित करें?

उदा

string[] testArray = { "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8" }; 

अगर हम n = 3 लेने में विभाजित किया जाना चाहिए।

string[] A1 = {"s1", "s2", "s3"}; 
string[] A2 = {"s4", "s5", "s6"}; 
string[] A3 = {"s7", "s8"}; 

LINQ का उपयोग करके एक आसान तरीका हो सकता है?

उत्तर

23

यह 3 तत्वों होने स्ट्रिंग सरणियों की एक सरणी उत्पन्न करेगा: यदि यह वास्तव में सरणियों है कि आप के साथ नहीं बल्कि सामान्य IEnumerables से, और विशेष रूप से अगर सरणियों बहुत बड़े हैं काम कर रहे हैं है

int i = 0; 
var query = from s in testArray 
      let num = i++ 
      group s by num/3 into g 
      select g.ToArray(); 
var results = query.ToArray(); 
+1

+1, इस दृष्टिकोण का एकमात्र नकारात्मक पक्ष यह है कि यह उत्सुकता से मूल्यांकन किया जाता है। एक तत्व को वापस करने से पहले पूरी क्वेरी को संसाधित किया जाना चाहिए। – JaredPar

+0

@ जेरेडपायर: प्वाइंट अच्छी तरह से लिया गया; हालांकि, संग्रह के आकार, या प्रसंस्करण की प्रकृति के आधार पर, आलसी मूल्यांकन अतिरंजित किया जा सकता है। फिर भी, वैध आलसी दृष्टिकोण प्रदान करने के लिए अपने समाधान में +1 करें। – kbrimington

9

मुझे नहीं लगता कि इसके लिए एक महान अंतर्निहित विधि है लेकिन आप निम्न में से एक लिख सकते हैं।

public static IEnumerable<IEnumerable<T>> GroupInto<T>(
    this IEnumerable<T> source, 
    int count) { 

    using (var e = source.GetEnumerator()) { 
    while (e.MoveNext()) { 
     yield return GroupIntoHelper(e, count); 
    } 
    }  
} 

private static IEnumerable<T> GroupIntoHelper<T>(
    IEnumerator<T> e, 
    int count) { 

    do { 
    yield return e.Current; 
    count--; 
    } while (count > 0 && e.MoveNext()); 
} 
+0

बिल्कुल सही जवाब। लेकिन इस मामले में समस्या को हल करने का एक उदाहरण प्रदान करना चाहिए। –

2

, तो यह विधि इसे करने के लिए एक बहुत तेज़ और स्मृति प्रभावशाली तरीका है। यदि आप वास्तव में केवल एक LINQ कथन चाहते हैं, तो कभी नहीं।

private static T[][] SliceArray<T>(T[] source, int maxResultElements) 
    { 
     int numberOfArrays = source.Length/maxResultElements; 
     if (maxResultElements * numberOfArrays < source.Length) 
      numberOfArrays++; 
     T[][] target = new T[numberOfArrays][]; 
     for (int index = 0; index < numberOfArrays; index++) 
     { 
      int elementsInThisArray = Math.Min(maxResultElements, source.Length - index * maxResultElements); 
      target[index] = new T[elementsInThisArray]; 
      Array.Copy(source, index * maxResultElements, target[index], 0, elementsInThisArray); 
     } 
     return target; 
    } 
5
int size = 3; 
var results = testArray.Select((x, i) => new { Key = i/size, Value = x }) 
         .GroupBy(x => x.Key, x => x.Value, (k, g) => g.ToArray()) 
         .ToArray(); 

आप कोई आपत्ति नहीं है के रूप में IEnumerable<IEnumerable<T>> बजाय T[][] तो आप पूरी तरह ToArray कॉल को छोड़ सकते हैं परिणाम टाइप किया जा रहा है:

int size = 3; 
var results = testArray.Select((x, i) => new { Key = i/size, Value = x }) 
         .GroupBy(x => x.Key, x => x.Value); 
1

MoreLinq प्रदान करता है Batch विस्तार विधि

1

आप इस एक्सटेंशन का उपयोग कर सकते हैं

public static class Extension 
{ 
    private static IEnumerable<TList> Split<TList, T>(this TList value, int countOfEachPart) where TList : IEnumerable<T> 
    { 
     int cnt = value.Count()/countOfEachPart; 
     List<IEnumerable<T>> result = new List<IEnumerable<T>>(); 
     for (int i = 0; i <= cnt; i++) 
     { 
      IEnumerable<T> newPart = value.Skip(i * countOfEachPart).Take(countOfEachPart).ToArray(); 
      if (newPart.Any()) 
       result.Add(newPart); 
      else 
       break; 
     } 

     return result.Cast<TList>(); 
    } 

    public static IEnumerable<IDictionary<TKey, TValue>> Split<TKey, TValue>(this IDictionary<TKey, TValue> value, int countOfEachPart) 
    { 
     IEnumerable<Dictionary<TKey, TValue>> result = value.ToArray() 
                  .Split(countOfEachPart) 
                  .Select(p => p.ToDictionary(k => k.Key, v => v.Value)); 
     return result; 
    } 

    public static IEnumerable<IList<T>> Split<T>(this IList<T> value, int countOfEachPart) 
    { 
     return value.Split<IList<T>, T>(countOfEachPart); 
    } 

    public static IEnumerable<T[]> Split<T>(this T[] value, int countOfEachPart) 
    { 
     return value.Split<T[], T>(countOfEachPart); 
    } 

    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> value, int countOfEachPart) 
    { 
     return value.Split<IEnumerable<T>, T>(countOfEachPart); 
    } 
} 
संबंधित मुद्दे