Метод LINQ для группировки коллекции в подгруппы с указанным количеством элементов - PullRequest
3 голосов
/ 05 июля 2010

Существует ли метод LINQ для группировки данной коллекции в подгруппы с указанным количеством элементов, я имею в виду, что-то вроде метода grouped в Scala.
Например, в Scala, List(89, 67, 34, 11, 34).grouped(2) дает List(List(89, 67), List(34, 11), List(34)).

Если такого метода не существует, каким будет LINQ способ сделать это?

Ответы [ 3 ]

2 голосов
/ 05 июля 2010

Вот веб-сайт, который, кажется, имеет некоторый пример кода, чтобы делать то, что вы хотите: http://www.chinhdo.com/20080515/chunking/

Итак, что вы можете сделать, это воспользоваться этим методом и создать метод расширения.

Пример метода расширения:

static class ListExtension
{
    public static List<List<T>> BreakIntoChunks<T>(this List<T> list, int chunkSize)
    {
        if (chunkSize <= 0)
        {
            throw new ArgumentException("chunkSize must be greater than 0.");
        }

        List<List<T>> retVal = new List<List<T>>();

        while (list.Count > 0)
        {
            int count = list.Count > chunkSize ? chunkSize : list.Count;
            retVal.Add(list.GetRange(0, count));
            list.RemoveRange(0, count);
        }

        return retVal;
    }
}
2 голосов
/ 05 июля 2010

Да, вы можете. Но вы можете поспорить, если это очень красиво ...

  Int64[] aValues = new Int64[] { 1, 2, 3, 4, 5, 6 };
  var result = aValues
          .Select( ( x, y ) => new KeyValuePair<Int64, Int32>( x, y ) )
          .GroupBy( x => x.Value / 2 )
          .Select( x => x.Select( y => y.Key ).ToList() ).ToList();

Как это работает:

Выберите x и y из исходной коллекции, где x - фактическое значение, а y - индекс из этого в данной коллекции. Затем сгруппируйте по целочисленному отклонению индекса и желаемой длины группировки (в этом примере 2 ).

Группировка по целочисленному отклонению округляется до нижнего значения, поэтому 0/2 = 0 , 1/2 = 0 и т. Д., Что даст нам необходимое значение категории группировки , Это то, против чего мы здесь группируем.

Для результата выберите только значения, сгруппированные в списках, и верните их как набор списков.

2 голосов
/ 05 июля 2010

Вы можете попробовать подход, показанный в этом ответе на этот аналогичный вопрос .

public static class GroupingExtension
{
    public static IEnumerable<IEnumerable<T>> Grouped<T>(
        this IEnumerable<T> input,
        int groupCount)
    {
        if (input == null) throw new ArgumentException("input");
        if (groupCount < 1) throw new ArgumentException("groupCount");

        IEnumerator<T> e = input.GetEnumerator();

        while (true)
        {
            List<T> l = new List<T>();
            for (int n = 0; n < groupCount; ++n)
            {
                if (!e.MoveNext())
                {
                    if (n != 0)
                    {
                        yield return l;
                    }
                    yield break;
                }
                l.Add(e.Current);
            }
            yield return l;
        }
    }
}

Использовать так:

List<int> l = new List<int>{89, 67, 34, 11, 34};
foreach (IEnumerable<int> group in l.Grouped(2)) {
    string s = string.Join(", ", group.Select(x => x.ToString()).ToArray());
    Console.WriteLine(s);
}

Результат:

89, 67
34, 11
34
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...