GroupBy在条件上返回Count和Value

时间:2016-12-19 14:39:27

标签: c# linq group-by

这个问题的标题有点奇怪,所以谢谢你。

我想要达到的目的是在数字上使用groupby,但仅限于计数值为3 时。

为了澄清......作为一个例子,我有以下数组值。

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

如果我在这样的nums上做一个小组

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

它将返回以下

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

我真正想要的是这个。

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

可以使用GroupBy方法来实现这一目标,还是需要采用不同的方法?

2 个答案:

答案 0 :(得分: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}

答案 1 :(得分: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}