2016-11-10 177 views
0

我需要幫助 我有表:LINQ的GROUP BY,ORDER BY值

Id   Day     Group  Value 
------------------------------------------------- 
    1   2016-10-11   1   10.5 
    2   2016-10-11   1   10.8 
    3   2016-10-11   1   10.7 
    4   2016-10-11   1   10.6 
    5   2016-10-11   1   10.5 
    6   2016-10-11   1   10.4 
    7   2016-10-11   1   10.8 
    8   2016-10-11   1   10.2 
    9   2016-10-11   1   10.0 
    10   2016-10-11   1   10.9 
    11   2016-10-11   2   10.1 
    12   2016-10-11   2   10.0 
    13   2016-10-11   2   10.1 
    14   2016-10-11   2   10.6 
    15   2016-10-11   2   10.7 
    16   2016-10-11   2   10.2 
    17   2016-10-11   2   10.0 
    18   2016-10-11   2   10.5 
    19   2016-10-11   2   10.5 
    20   2016-10-11   2   10.8 
    21   2016-10-12   1   11.1 
    22   2016-10-12   1   11.7 
    23   2016-10-12   1   11.0 
    24   2016-10-12   1   11.4 
    25   2016-10-12   1   11.7 
    26   2016-10-12   1   11.8 
    27   2016-10-12   1   11.1 
    28   2016-10-12   1   11.1 
    29   2016-10-12   1   11.4 
    30   2016-10-12   1   11.6 
    31   2016-10-12   2   11.9 
    32   2016-10-12   2   11.6 
    ... 

而且我想

  • 爲了通過價值
  • 逐組由
  • 並且獲得類似的價值:

[[[10.5,10.8],[10.0,10.1]],[[11.1,11.7],[11.6,11.9]]](例如)

分別我需要這個值更多的工作,當我得到價值像例子中,我獲得日更多的價值。然後我將這批分成4批,然後我從每組中選擇第一個值。因此,我將爲每個組設置4個值,並且爲1天,我將有2個批次,每個批次將有4個值。而且因爲我需要每個批次中有最後一個值等5個值,所以我找到最大值並將其添加到具有4個值的批次中。我不知道你明白所以我的代碼:

​​

更新:

這項工作:

var result = db.Values 
    .Where(x => (DbFunctions.TruncateTime(x.Day)) >= startDate 
    && (DbFunctions.TruncateTime(x.Day)) <= endDate) 
    .GroupBy(x => new { Day = x.Day, Group = x.Group }) 
    .Select(x => x.Select(y => y.Value).OrderBy(z => z).ToList()).ToList(); 

我得到這個:

[ 
[10.0, 10.2, 10.4, 10.5, 10.5, 10.6, 10.7, 10.8, 10.8, 10.9], 
[10.0, 10.0, 10.1, 10.1, 10.2, 10.5, 10.5, 10.6, 10.7, 10.8], 
[11.0, 11.1, 11.1, 11.1, 11.4, 11.4, 11.6, 11.7, 11.7, 11.8], 
[...] 
] 

但我在這種情況下需要對每個批次進行拆分2部分,並從該部分中選擇第一個值。因此,我將有2個值,然後我想從這個批次CONCAT 2值最高值,因此在這個例子中我的最終結果將是:

[ 
[10.0, 10.6, 10.9], 
[10.0, 10.2, 10.8], 
[11.0, 11.4, 11.8], 
[...] 
] 

分裂我用這個方法:

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int length) 
     { 
      if (length <= 0) 
       throw new ArgumentOutOfRangeException("length"); 

      var section = new List<T>(length); 

      foreach (var item in source) 
      { 
       section.Add(item); 

       if (section.Count == length) 
       { 
        yield return section.AsReadOnly(); 
        section = new List<T>(length); 
       } 
      } 

      if (section.Count > 0) 
       yield return section.AsReadOnly(); 
     } 
+0

所以要Concat的一些值,其將按照羣組失去了發言。這裏是一個關於通過linq連接這些值的問題:[link](http://stackoverflow.com/questions/18203169/field-concatenation-based-on-group-in-linq)。所以你可以根據需要多次使用組,然後連接數值。之後,您可以訂購結果數據。 – Jenism

回答

1

試試這個

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 

namespace ConsoleApplication23 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      DataTable dt = new DataTable(); 
      dt.Columns.Add("ID", typeof(int)); 
      dt.Columns.Add("Day", typeof(DateTime)); 
      dt.Columns.Add("Group", typeof(int)); 
      dt.Columns.Add("Value", typeof(decimal)); 

      dt.Rows.Add(new object[] {1 , DateTime.Parse("2016-10-11"), 1, 10.5}); 
      dt.Rows.Add(new object[] {2 , DateTime.Parse("2016-10-11"), 1, 10.8}); 
      dt.Rows.Add(new object[] {3 , DateTime.Parse("2016-10-11"), 1, 10.7}); 
      dt.Rows.Add(new object[] {4 , DateTime.Parse("2016-10-11"), 1, 10.6}); 
      dt.Rows.Add(new object[] {5 , DateTime.Parse("2016-10-11"), 1, 10.5}); 
      dt.Rows.Add(new object[] {6 , DateTime.Parse("2016-10-11"), 1, 10.4}); 
      dt.Rows.Add(new object[] {7 , DateTime.Parse("2016-10-11"), 1, 10.8}); 
      dt.Rows.Add(new object[] {8 , DateTime.Parse("2016-10-11"), 1, 10.2}); 
      dt.Rows.Add(new object[] {9 , DateTime.Parse("2016-10-11"), 1, 10.0}); 
      dt.Rows.Add(new object[] {10, DateTime.Parse("2016-10-11"), 1, 10.9}); 
      dt.Rows.Add(new object[] {11, DateTime.Parse("2016-10-11"), 2, 10.1}); 
      dt.Rows.Add(new object[] {12, DateTime.Parse("2016-10-11"), 2, 10.0}); 
      dt.Rows.Add(new object[] {13, DateTime.Parse("2016-10-11"), 2, 10.1}); 
      dt.Rows.Add(new object[] {14, DateTime.Parse("2016-10-11"), 2, 10.6}); 
      dt.Rows.Add(new object[] {15, DateTime.Parse("2016-10-11"), 2, 10.7}); 
      dt.Rows.Add(new object[] {16, DateTime.Parse("2016-10-11"), 2, 10.2}); 
      dt.Rows.Add(new object[] {17, DateTime.Parse("2016-10-11"), 2, 10.0}); 
      dt.Rows.Add(new object[] {18, DateTime.Parse("2016-10-11"), 2, 10.5}); 
      dt.Rows.Add(new object[] {19, DateTime.Parse("2016-10-11"), 2, 10.5}); 
      dt.Rows.Add(new object[] {20, DateTime.Parse("2016-10-11"), 2, 10.8}); 
      dt.Rows.Add(new object[] {21, DateTime.Parse("2016-10-12"), 1, 11.1}); 
      dt.Rows.Add(new object[] {22, DateTime.Parse("2016-10-12"), 1, 11.7}); 
      dt.Rows.Add(new object[] {23, DateTime.Parse("2016-10-12"), 1, 11.0}); 
      dt.Rows.Add(new object[] {24, DateTime.Parse("2016-10-12"), 1, 11.4}); 
      dt.Rows.Add(new object[] {25, DateTime.Parse("2016-10-12"), 1, 11.7}); 
      dt.Rows.Add(new object[] {26, DateTime.Parse("2016-10-12"), 1, 11.8}); 
      dt.Rows.Add(new object[] {27, DateTime.Parse("2016-10-12"), 1, 11.1}); 
      dt.Rows.Add(new object[] {28, DateTime.Parse("2016-10-12"), 1, 11.1}); 
      dt.Rows.Add(new object[] {29, DateTime.Parse("2016-10-12"), 1, 11.4}); 
      dt.Rows.Add(new object[] {30, DateTime.Parse("2016-10-12"), 1, 11.6}); 
      dt.Rows.Add(new object[] {31, DateTime.Parse("2016-10-12"), 2, 11.9}); 
      dt.Rows.Add(new object[] {32, DateTime.Parse("2016-10-12"), 2, 11.6}); 

      var results = dt.AsEnumerable() 
       .GroupBy(x => new { day = x.Field<DateTime>("Day"), group = x.Field<int>("Group")}) 
       .Select(x => x.Select(y => y.Field<decimal>("Value")).OrderBy(z => z).ToList()).ToList(); 

      List<List<decimal>> groups = new List<List<decimal>>(); 
      const int NUM_GROUPS = 2; 
      foreach (var result in results) 
      { 
       int size = result.Count; 
       int groupSize = (int)(size/NUM_GROUPS); //round down 

       List<decimal> newGroup = new List<decimal>() { result[0] }; 
       groups.Add(newGroup); 
       for (int groupNum = 0; groupNum < NUM_GROUPS; groupNum++) 
       { 
        newGroup.Add(result.Skip(groupNum * groupSize).Take(groupSize).Max()); 
       } 
      } 


     } 
    } 
} 
+0

好的這項工作我得到這樣的東西: [ [1,2,3,....] [1,2,3,....] [1,2,3,... ...] [1,2,3,....] [1,2,3,....] ] 但是,我怎樣才能拆分這批次選擇每批第一個值,並找到最大值和添加這個最大值。 實施例 [ [4,6,8,9,10] [2,4,5,8,8] [1,1,6,9,10] [1,2,4,4, 7] [3,3,7,8,10] ] 對於分割我使用的方法工作。 – Marko

+0

請更好地解釋 – jdweng

+0

如何在我的代碼中看到我得到的每個組,我將其分成4部分,並在每個部分中選擇第一個值,這樣我就有了4個值。然後,我將每個組的最大值最小化爲4個值,所以最後我對每個組都有5個值。在這種情況下,我應該爲每一天的每個團隊設定5個價值。 – Marko

0

這裏是我是如何做的樣品,我相信一定有產生輸出字符串的一個更優雅的方式,雖然

static void Main(string[] args) 
    { 
     List<Example> samples = new List<Example>(); 
     samples.Add(new Example(1, DateTime.Parse("2016-10-11"), 1, 10.5)); 
     samples.Add(new Example(2, DateTime.Parse("2016-10-11"), 1, 10.8)); 
     samples.Add(new Example(3, DateTime.Parse("2016-10-11"), 2, 10.1)); 
     samples.Add(new Example(4, DateTime.Parse("2016-10-11"), 2, 10.0)); 
     samples.Add(new Example(5, DateTime.Parse("2016-10-12"), 1, 11.1)); 
     samples.Add(new Example(6, DateTime.Parse("2016-10-12"), 1, 11.7)); 
     samples.Add(new Example(7, DateTime.Parse("2016-10-12"), 2, 11.9)); 
     samples.Add(new Example(8, DateTime.Parse("2016-10-12"), 2, 11.6)); 

     var daily_results = samples.GroupBy(g => new { g.group, g.date }).GroupBy(g => g.Key.date); 

     StringBuilder sb = new StringBuilder(); 

     sb.Append("["); 
     foreach (var group_result in daily_results) 
     { 
      sb.Append("["); 
      foreach(var result in group_result) 
      { 
       sb.Append($"[{string.Join(",", result.OrderBy(r => r.value).Select(r => r.value))}]"); 
      } 
      sb.Append("]"); 
     } 
     sb.Append("]"); 

     Console.WriteLine(sb); 
     Console.Read(); 
    } 
} 
class Example 
{ 
    public int id; 
    public DateTime date; 
    public int group; 
    public double value; 
    public Example(int i, DateTime d, int g, double v) 
    { 
     id = i; 
     date = d; 
     group = g; 
     value = v; 
    } 
} 

UPDATE:輸出代碼可以簡化如下:

 var daily_results = samples.GroupBy(g => new { g.group, g.date }).GroupBy(g => g.Key.date); 

     string output = string.Empty; 

     daily_results.ToList().ForEach(grp => 
      { 
       output += "["; 
       grp.ToList().ForEach(res => 
       { 
        output += $"[{string.Join(",", res.OrderBy(r => r.value).Select(r => r.value))}],"; 
       }); 
       output = output.TrimEnd(',') + "],"; 
      }); 
     Console.WriteLine($"[{output.TrimEnd(',')}]"); 
     Console.Read();