2014-10-29 3 views
2

у меня есть список заказов и нужно создавать группы аналогичных заказов эффективным способом (желательно без отходили все заказы и сравнения вручную)Linq к Entities группировки по нескольким полям с оператором или

Каждый заказ имеет идент и адрес электронной почты с дополнительными полями Почтовый индекс и страна

Так мне нужно, чтобы создать группы по следующим правилам

Если заказ имеет тот же (USERID или адрес электронной почты) и (postco де и страна) место в группе

Учитывая следующий объект и данные

public class Order 
{ 
     public int UserId { get; set; } 
     public int OrderId { get; set; } 
     public string Email { get; set; } 
     public int PostCode { get; set; } 
     public string Country { get; set; } 
} 

Пример данных

OrderId UserId Email PostCode Country 
1  1  blah1 111   au 
2  1  blah2 111   au 
3  2  blah1 111   au 
4  2  blah2 111   au 
5  3  blah3 111   nz 
6  3  blah3 111   nz 

Пример Результаты

Group 1 
1  1  blah1 111   au 
2  1  blah2 111   au 
3  2  blah1 111   au 
4  2  blah2 111   au 

Group 2 
5  3  blah3 111   nz 
6  3  blah3 111   nz 

Единственный способ я могу кажется, думают об этом через ручную итерацию n в памяти

Возможно ли это связать с Linq объектами?

Update

После изучения этого на некоторое время, я думаю, что я пришел к выводу, что единственный способ добиться того, чего я хочу, это возможно сделать 2 groupbys и вручную объединить их в памяти

Update2

Думая об этом логически не существует, казалось бы, не элегантное решение этой проблемы в LINQ и, возможно, потребуется сделать с SQL и КТР или каким-либо другим рекурсивного решения. Ill отметить близкое решение как правильное

ответ

0

Попробуйте это: -

var query = from ord in orders 
         group ord by new { ord.Country, ord.PostCode } into g 
         select new 
          { 
           Country = g.Key.Country, 
           PostCode = g.Key.PostCode, 
           Orders = g.GroupBy(x => x.OrderId) 
              .GroupBy(i => i.Count() > 1 ? 
               new { OrderID = i.Key, Email = default(string) } 
               : new { OrderID = default(int), i.First().Email }) 
              .Select(o => o.Count() == 1 ? 
               new { o.Key, Orders = o.First().ToList() } 
               : new { o.Key, Orders = o.Select(z => z.First()).ToList() }) 
          }; 

Вот полный рабочий Fiddle.

+0

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

0

Предполагая, что ваш Order Class будет, как показано ниже:

public class Order 
{ 
     public int UserId { get; set; } 
     public int OrderId { get; set; } 
     public string Email { get; set; } 
     public int PostCode { get; set; } 
     public string Country { get; set; } 
} 

Предполагая, и Grouping the List of Orders Как ниже:

public List<List<Order>> grouping() 
{   
      // List of Orders to Group 
      List<Order> orderList = new List<Order>(); 
      orderList.Add(new Order { UserId = 1, OrderId = 2007, Email = "[email protected]", PostCode = 111, Country = "India" }); 
      orderList.Add(new Order { UserId = 2, OrderId = 2007, Email = "[email protected]", PostCode = 111, Country = "India" }); 
      orderList.Add(new Order { UserId = 3, OrderId = 2007, Email = "[email protected]", PostCode = 111, Country = "India" }); 
      orderList.Add(new Order { UserId = 4, OrderId = 2008, Email = "[email protected]", PostCode = 111, Country = "India" }); 
      orderList.Add(new Order { UserId = 5, OrderId = 2008, Email = "[email protected]", PostCode = 111, Country = "India" }); 
      orderList.Add(new Order { UserId = 6, OrderId = 2001, Email = "[email protected]", PostCode = 111, Country = "India" }); 

      // Grouping 
      var groupedOrderList = orderList 
       .GroupBy(u => u.OrderId) 
       .Select(grp => grp.ToList()).ToList(); // Groping the Records based on the OrderId 

      return groupedOrderList; // The Result will be List<List<Order>> 
} 

Ваша группа заявление будет group by OrderId. Результат будет таким, как вы ожидали, как показано выше.

Update:

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

Как показано ниже:

.GroupBy(u => u.OrderId & u.UserId) 
+0

Спасибо за ваш ответ, однако эта группа принадлежит UserId или электронной почте, так как я не уверен, как я поместил бы другие conidtions (включая OR) в группу по статусу –

+0

Если вы хотите, вы можете дополнительно добавить это также. Подобно '.GroupBy (u => u.UserId)' Или если вы хотите, чтобы все поля были сгруппированы, сделайте так: .GroupBy (u => u.OrderId && u.UserId && u.Email) ' – RajeshKdev

+0

@Saruman I просто обновил свой ответ снова. Это работало? – RajeshKdev

1

Здесь я сделал группу по более чем 1 колонке,

OrderViewModel OrderList =from ord in order 
     group ord by new 
     { 
      ord.PostCode, 
      ord.Country, 
      ord.UserID, 
      ord.Email, 
      ord.OrderID 
     } into gr 
     select new OrderViewModel 
     { 
      OrderID = gr.Key.OrderID, 
      UserID = gr.Key.UserID, 
      Email = gr.Key.Email, 
      PostCode=gr.key.PostCode, 
      Country=gr.key.Country, 
      OrderList= gr.ToList() 
     }; 

где OrderViewModel нечто ::

public class Order 
{ 
     public int UserId { get; set; } 
     public int OrderId { get; set; } 
     public string Email { get; set; } 
     public int PostCode { get; set; } 
     public string Country { get; set; } 
     public List<Order> OrderList { get; set; } 
} 

Где вы необходимо определить приоритет группирования данных, & Данные, которые вы не хотите группировать, будут отобраны в виде списка.

+0

+1 Да. Это может быть еще один ответ. Но каков тип возвращаемого результата? Если я не хочу использовать здесь 'var'. – RajeshKdev

+0

@RJK Я отредактировал свой ответ, maybw, это поможет вам – Rahul

Смежные вопросы