2010-08-18 56 views
17

cách tốt nhất để nhóm là gì một mảng vào một danh sách các mảng n phần tử mỗi trong C# 4.Làm thế nào để tách một mảng thành một nhóm các phần tử n?

ví dụ

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

nên được chia thành nếu chúng ta lấy n = 3.

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

Có thể là cách đơn giản khi sử dụng LINQ?

Trả lời

23

này sẽ tạo ra một mảng của mảng chuỗi có 3 yếu tố:

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, Nhược điểm duy nhất của phương pháp này là nó được đánh giá háo hức. Toàn bộ truy vấn phải được xử lý trước khi một phần tử có thể được trả về. – JaredPar

+0

@JaredPar: Điểm được chụp tốt; tuy nhiên, tùy thuộc vào kích thước của bộ sưu tập, hoặc bản chất của quá trình xử lý, việc đánh giá lười biếng có thể bị đánh giá quá cao. Mặc dù vậy, +1 cho giải pháp của bạn để cung cấp phương pháp tiếp cận lười biếng hợp lệ. – kbrimington

9

Tôi không nghĩ rằng có một phương pháp tích hợp sẵn cho điều này nhưng bạn có thể viết một phương pháp như sau.

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

Câu trả lời hoàn hảo. Nhưng nên cung cấp một ví dụ về cách giải quyết vấn đề trong câu hỏi. –

2

Nếu nó thực sự là mảng mà bạn đang làm việc với hơn IEnumerables nói chung và đặc biệt là nếu các mảng rất lớn, sau đó phương pháp này là một cách nhanh chóng và bộ nhớ hiệu quả để làm điều đó. Nếu bạn thực sự chỉ muốn có một câu lệnh LINQ, thì đừng bao giờ.

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(); 

Nếu bạn không nhớ các kết quả được đánh máy như IEnumerable<IEnumerable<T>> hơn T[][] sau đó bạn có thể bỏ qua các cuộc gọi hoàn toàn 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 cung cấp Batch phương pháp khuyến nông

1

Bạn có thể sử dụng Tiện ích mở rộng này

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); 
    } 
} 
Các vấn đề liên quan