代码之家  ›  专栏  ›  技术社区  ›  Amitabh

如何将数组拆分为一组n个元素?

  •  18
  • Amitabh  · 技术社区  · 14 年前

    什么是将数组分组为c#4中n个元素的数组的最佳方法。

    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"};
    

    6 回复  |  直到 14 年前
        1
  •  26
  •   kbrimington    14 年前

    这将生成一个包含3个元素的字符串数组:

    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();
    
        2
  •  9
  •   JaredPar    14 年前

    我不认为有一个伟大的内置方法,但你可以写一个如下。

    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());
    }
    
        3
  •  7
  •   LukeH    14 年前
    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);
    
        4
  •  2
  •   Jeffrey L Whitledge    14 年前

    如果实际使用的是数组,而不是一般的IEnumerables,尤其是数组非常大的情况下,那么这种方法是一种非常快速和高效的方法。如果你真的只想要一个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
  •  1
  •   Deniz Kocaboğa    9 年前

    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);
        }
    }
    
        6
  •  1
  •   Mauro Sampietro    7 年前

    MoreLinq 提供 Batch