2016-11-10 2 views
0

je besoin d'aide je Tableau:groupe Linq par, ordre par des valeurs

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 
    ... 

Je veux

  • commande par valeur
  • groupe
  • par groupe
  • groupe par jour
  • et obtenir uniquement la valeur comme:

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

je besoin de travailler Respectivement avec cette valeur plus, quand je reçois valeur comme exemple, je reçois plus de valeur à jour. Et puis j'ai divisé ce lot en 4 lots et ensuite je choisis juste la première valeur de chaque groupe. Donc, je vais avoir 4 valeur pour chaque groupe et pour 1 jour, j'aurai 2 lot et chaque lot aura 4 valeur. Et parce que j'ai besoin de la valeur 5 comme dernière valeur dans chaque lot, je trouve Max Value et l'ajoute au lot avec 4 valeur. Je ne sais pas si vous comprenez donc il est mon code:

var valueList = await Task.Factory.StartNew(() => 

    (
     from pv in db.Values 
     where DbFunctions.TruncateTime(pv.Day) >= startDate  
     && DbFunctions.TruncateTime(pv.Day) <= endDate   
     orderby pv.Value 
     //group pv by pv.Day into gpv 
     select pv 
    )); 

var group1 = await Task.Factory.StartNew(() => (
(
    from vl in valueList 
    where vl.Group == 1 
    select vl) 
)); 

var group2 = await Task.Factory.StartNew(() => 
(
    from vl in valueList 
    where vl.Group == 2 
    select vl 
)); 

var group3 = await Task.Factory.StartNew(() => 
(
    from vl in valueList 
    where vl.Group == 3 
    select vl 
)); 


var group1Split = group1.Split(group1.Count()/4 + 1).Select(x => x.First()); 
var group1Max = group1.Max(); 
var group2Split = group2.Split(group2.Count()/4 + 1).Select(x => x.First()); 
var group2Max = group2.Max(); 
var group3Split = group3.Split(group3.Count()/4 + 1).Select(x => x.First()); 
var group3Max = group3.Max(); 

var group1Values = group1Split.Concat(group1Max); 
var group2Values = group2Split.Concat(group2Max); 
var group3Values = group3Split.Concat(group3Max); 

var groupAllValues = group1Values.Concat(group2Values).Concat(group3Values); 
var groupSplitAllValues = groupAllValues.Split(5); 

return Request.CreateResponse(HttpStatusCode.OK, groupSplitAllValues.ToList()); 

Mise à jour:

ce travail:

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(); 

Je reçois ceci:

[ 
[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], 
[...] 
] 

Mais je besoin de diviser chaque lot à dans ce cas 2 partie et sélectionnez la première valeur de cette partie. Je vais donc avoir 2 valeur et je veux concat à 2 valeur valeur maximale de ce lot si cet exemple mon résultat final sera:

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

pour diviser j'utiliser cette méthode:

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

si vous voulez concaténer des valeurs qui seraient perdues par le groupe par des déclarations. voici une question concernant la concaténation de ces valeurs par linq: [link] (http://stackoverflow.com/questions/18203169/field-concatenation-based-on-group-in-linq). Vous utilisez donc le groupe autant de fois que vous le souhaitez et ensuite concattez les valeurs. Après cela, vous pouvez commander les données qui en résultent. – Jenism

Répondre

1

Essayez cette

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

Ok ce travail je reçois quelque chose comme ceci: [ [1, 2, 3, ....] [1, 2, 3, ....] [1, 2, 3, ... Mais comment puis-je diviser ce lot en sélectionnant la première valeur pour chaque lot et trouver la valeur Max et ajoutez ces valeurs max. Exemple [ [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] ] Pour split, j'utilise une méthode qui fonctionne. – Marko

+0

S'il vous plaît expliquer mieux – jdweng

+0

Comment vous pouvez voir dans mon code chaque groupe que je reçois je divisé en 4 parties et sélectionnez juste la première valeur dans chaque partie, donc j'ai 4 valeur. Ensuite, je Concat Max valeur de chaque groupe à 4 valeurs donc à la fin j'ai 5 valeur pour chaque groupe. Dans ce cas, je devrais avoir 5 valeur pour chaque groupe pour chaque jour. – Marko

0

Voici un échantillon de la façon dont je l'ai fait, je suis sûr qu'il doit y avoir une façon plus élégante de générer la chaîne de sortie si

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; 
    } 
} 

MISE À JOUR: Code de sortie peut être simplifiée comme suit:

 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();