2016-11-10 262 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();