2016-12-19 12 views
1

この質問のタイトルは少し奇妙なので、ありがたいです。GroupByが条件と数値を返す

私が達成したいのは、値のが3の場合にのみ、numberにgroupbyを使用することです。

例として、次の値の配列があります。

int[] nums= new int[] { 1, 1, 1, 3, 1 }; 

私はこの

var vals = dice.GroupBy(t => t).Select(p => new { Value = p.Key, Count = p.Count() }).ToList(); 

ようNUMS上でグループをすれば、それは戻りますが、次の

{Value = 1, Count = 4}, 
{Value = 3, Count = 1} 

と私が実際に欲しい本であるだろう。

{Value = 1, Count = 3}, 
{Value = 1, Count = 1} 
{Value = 3, Count = 1} 

これを達成するためにGroupByメソッドを使用できますか、またはアプローチが異なる必要がありますか?

+0

'Value'の値はもともとグループのキーだったものです。 'GroupBy'の本質は、あなたが同じキーを一つの列挙に二度出現させないことです。 – Abion47

+1

わかりません。 '{1,1,1,1,1,1} '(7つのもの)から期待される出力は何ですか? –

答えて

2

あなたはチャンクに各グループを作るために、このanswerのこのChunkify修正版を使用することができます。

static class ChunkExtension 
{ 
    public static IEnumerable<IEnumerable<T>> Chunkify<T>(
     this IEnumerable<T> source, int size) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (size < 1) throw new ArgumentOutOfRangeException("size"); 
     using (var iter = source.GetEnumerator()) 
     { 
      while (iter.MoveNext()) 
      { 
       var chunk = new List<T>(); 
       chunk.Add(iter.Current); 
       for (int i = 1; i < size && iter.MoveNext(); i++) 
        chunk.Add(iter.Current); 

       yield return chunk; 
      } 
     } 
    } 
} 

int[] nums = new int[] { 1, 1, 1, 3, 1 }; 

var groups = nums.GroupBy(n => n) 
       .Select(g => g.Chunkify(3) 
           .Select(x => new { Value = g.Key, Count = x.Count() })) 
       .SelectMany(g => g); 

あなたはこのような何かを得る:

{Value = 1, Count = 3}, 
{Value = 1, Count = 1} 
{Value = 3, Count = 1} 
+0

私はこれがOPの目的ではないと思います。これは結果を任意に3つのオブジェクトのグループ(せいぜい)に分割しますが、OPはソースリスト内の隣接するオブジェクトだけをグループ化する 'GroupBy'の変形を使用したいと考えています。 – Abion47

2

を私はネイティブLINQがあるとは思いませんあなたが探しているもののためのソリューション。 (存在する場合あるいは、それはおそらく多少大きくて扱いにくいことがあります。)しかし、あなたが仕事をする必要があります拡張メソッドを書くことができます:

public static class IEnumerableExtensions 
{ 
    public class Grouping<TKey, TElement> : IGrouping<TKey, TElement> 
    { 
     readonly List<TElement> elements; 

     public Grouping(TKey key, List<TElement> elems) 
     { 
      Key = key; 
      elements = elems; 
     } 

     public TKey Key { get; private set; } 

     public IEnumerator<TElement> GetEnumerator() 
     { 
      return this.elements.GetEnumerator(); 
     } 

     IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } 
    } 

    public static IEnumerable<IGrouping<TKey, TElement>> GroupByConcurrent<TSource, TKey, TElement>(
     this IEnumerable<TSource> source, 
     Func<TSource, TKey> keySelector, 
     Func<TSource, TElement> elementSelector) 
    where TKey : IEquatable<TKey> 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 

     TKey currentKey = default(TKey); 
     List<TElement> currentList = null; 

     foreach (var s in source) 
     { 
      var key = keySelector.Invoke(s); 
      var elem = elementSelector.Invoke(s); 

      if (!key.Equals(currentKey) || currentList == null) 
      { 
       if (currentList != null && currentList.Count > 0) 
        yield return new Grouping<TKey, TElement>(currentKey, currentList); 

       currentKey = key; 
       currentList = new List<TElement>(); 
      } 

      currentList.Add(elem); 
     } 

     if (currentList != null && currentList.Count > 0) 
      yield return new Grouping<TKey, TElement>(currentKey, currentList); 
    } 
} 

あなたがそうのようにそれを呼び出すことができます。

int[] nums = new int[] { 1, 1, 1, 3, 1 }; 

var concurGrouped = nums.GroupByConcurrent(t => t, t => t) 
         .Select(p => new { Value = p.Key, Count = p.Count() }) 
         .ToList(); 

// Contents of concurGrouped: 
// 
// { Value = 1, Count = 3}, 
// { Value = 1, Count = 1}, 
// { Value = 3, Count = 1} 
関連する問題