2010-07-26 2 views
2

Это связано с Another Question, что, по моему мнению, действительно связано с гораздо более простой проблемой, поэтому я задаю более простой вопрос здесь, в надежде, что это поможет мне решить более сложную задачу.Можете ли вы создать группировку на основе диапазонов?

Я хотел был бы иметь возможность создать группировку в запросе linq к sql для групп на основе диапазона данных в пределах другого набора данных. Тем не менее, я думаю, что он должен работать так же хорошо, как и в linq для объектов, поэтому давайте просто покончим с этим.

Представьте у вас есть два списка, содержащего значение

{100, 110, 120, 130, 140, 150, 160, 170} 
{115, 145, 180} 

Теперь я хотел бы группа первого списка, второго в виде диапазонов (значения, которые между каждой группой). То есть, я хотел бы группирование, как это (0 подразумеваются):

{0} {100, 110} 
{115} {120, 130, 140} 
{145} {150, 160, 170} 
{180} 

Я почти уверен, я буду злоупотреблять терминологию, и, вероятно, есть непонимание того, как Linq группы Оператором работы, но если вы понимаете, что я имею в виду, мне бы понравились некоторые предложения. Благодарю.

ответ

2

Ну, можно, конечно, выразить его в LINQ легко:

var x = from value in values 
     group value by ranges.Where(x => value >= x) 
          .DefaultIfEmpty() 
          .Last(); 

Но я очень сомневаюсь, что это будет работать в LINQ к SQL. В основном вам нужно найти простой способ сопоставления значения одной из этих категорий.

Полный пример:

using System; 
using System.Linq; 
using System.Collections.Generic; 

class Test 
{ 
    static void Main() 
    { 
     int[] values = {100, 110, 120, 130, 140, 150, 160, 170}; 
     int[] ranges = {115, 145, 180}; 

     var query = from value in values 
        group value by ranges.Where(x => value >= x) 
             .DefaultIfEmpty() 
             .Last(); 

     foreach (var group in query) 
     { 
      Console.WriteLine("{0}: {{{1}}}", group.Key, 
           string.Join(", ", group)); 
     } 
    } 
} 

Выход:.

0: {100, 110} 
115: {120, 130, 140} 
145: {150, 160, 170} 

Обратите внимание, что это не включать любые категории, которые не имеют каких-либо значений в

Также отметим, что это было бы проще (с использованием First() вместо Last()), если вы с удовольствием классифицируете несколько иначе:

115: {100, 110} 
145: {120, 130, 140} 
180: {150, 160, 170} 

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

EDIT: Вот версия, которая дает пустые группы. Это довольно ужасно, но IMO:

var query = from range in ranges 
      join value in values 
      on range equals ranges.Where(x => value >= x) 
            .DefaultIfEmpty() 
            .Last() into groups 
      select new { Key = range, Values = groups}; 

foreach (var group in query) 
{ 
    Console.WriteLine("{0}: {{{1}}}", group.Key, 
         string.Join(", ", group.Values)); 
} 
+0

Мне нужны категории без значений, но, возможно, я могу что-то понять. Ваши знания по этим темам никогда не перестают удивлять меня;) –

+0

Не можете ли вы просто сделать внешнее соединение, чтобы получить неиспользованные категории? – Gabe

+0

@Gabe: Внешние соединения нелегки в LINQ. Возможно, что групповое соединение будет работать, но это немного боль ... Я сейчас смотрю. –