Как создать выражение Linq, которое создает группы максимум из 100 объектов - PullRequest
2 голосов
/ 29 ноября 2010

У меня есть выражение LINQ, которое группирует клиентов из хранилища таблиц Azure по разделам.

Поскольку Azure поддерживает только пакетные операции с максимум 100 объектами одновременно (а объекты в пакете имеют одинаковый PartitionKey), мне нужно, чтобы каждая группа содержала максимум 100 объектов.

//How to complete this LINQ expression
var groups = customers.GroupBy(c => c.PartitionKey)....;

//Do some Azure table storage magic in parallel
Parallel.ForEach(groups , customersInGroup => {...});

Как мне заполнить выражение LINQ, чтобы в каждой группе было не более 100 клиентов? Это ... если коллекция клиентов, например. у меня 142 клиента с одинаковым PartitionKey, я хочу создать две группы ... одну группу со 100 клиентами и одну с 42 клиентами.

Ответы [ 4 ]

9 голосов
/ 29 ноября 2010

Для LINQ к объектам:

yourCollection
   .Select((v, i) => new {Value = v, Index = i}) 
   .GroupBy(x => x.Index / 100)

Не уверен, что это работает с Azure, хотя ...

4 голосов
/ 29 ноября 2010

В «нормальном» LINQ нет ничего, чтобы сделать это напрямую, но MoreLINQ имеет метод Batch, который может оказаться полезным:

public static IEnumerable<TResult> Batch<TSource, TResult>
    (this IEnumerable<TSource> source, int size,
     Func<IEnumerable<TSource>, TResult> resultSelector)

public static IEnumerable<IEnumerable<TSource>> Batch<TSource>
    (this IEnumerable<TSource> source, int size)

Обратите внимание, что в вашем случае вы, вероятно, захотите что-то вроде:

var groups = customers.GroupBy(c => c.PartitionKey).Batch(100, p => p.ToList());

так, чтобы возвращенные результаты были немедленно материализованы.

Конечно, это предполагает, что вы используете LINQ to Objects - если вы пытаетесь разделить через другого провайдера LINQ, я не уверен, как бы вы это сделали.

0 голосов
/ 29 ноября 2010

Это мой тест с применением «в» и «взять» для группировки результатов:

        static void Main(string[] args)
        {
            int[] numbers = new int[]
            {
                1,2,3,4,5,6,7,8,9,0
            };

            var result = from n in numbers group n by n%2
                         into group_numbers
                         select new { short_group = group_numbers.Take(3) };


            foreach(var v in result)
            {
                foreach (var v1 in v.short_group)
                {
                    Console.WriteLine(v1.ToString());
                }

                Console.WriteLine();
            }
        }

Вывод:

1
3
5

2
4
6
0 голосов
/ 29 ноября 2010

Это похоже на задание для .Skip и .Take, что-то вроде следующего:

result = collection.Skip(100 * i).Take(100);

Где i - номер страницы или группы, которую вы хотите получить.

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