您可以通過一些關鍵創建擴展項目的連續分組:
public static IEnumerable<IGrouping<TKey, T>> GroupConsecutive<T, TKey>(
this IEnumerable<T> source, Func<T, TKey> keySelector)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
else
{
List<T> list = new List<T>();
var comparer = Comparer<TKey>.Default;
list.Add(iterator.Current);
TKey groupKey = keySelector(iterator.Current);
while (iterator.MoveNext())
{
var key = keySelector(iterator.Current);
if (!list.Any() || comparer.Compare(groupKey, key) == 0)
{
list.Add(iterator.Current);
continue;
}
yield return new Group<TKey, T>(groupKey, list);
list = new List<T> { iterator.Current };
groupKey = key;
}
if (list.Any())
yield return new Group<TKey, T>(groupKey, list);
}
}
}
當然你可以返回IEnumerable<IList<T>>
,但是這與你想要的組的概念有點不同,因爲你也想知道哪個值被用來對項目序列進行分組。不幸的是沒有公開的實施IGrouping<TKey, TElement>
接口的,我們應該創造我們自己:
public class Group<TKey, TElement> : IGrouping<TKey, TElement>
{
private TKey _key;
private IEnumerable<TElement> _group;
public Group(TKey key, IEnumerable<TElement> group)
{
_key = key;
_group = group;
}
public TKey Key
{
get { return _key; }
}
public IEnumerator<TElement> GetEnumerator()
{
return _group.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
現在用法很簡單:
var groups = query.GroupConsecutive(i => i) // produces groups
.Select(g => new { g.Key, Count = g.Count() }); // projection
結果:
[
{ Key: 0, Count: 334 },
{ Key: 1, Count: 333 },
{ Key: 2, Count: 110 },
{ Key: 0, Count: 222 }
]
@SonerGönül,我回滾了編輯,因爲他們改變了問題的含義... –
也許你應該保留修復語法和格式? – Magus
@Magus我懶得把你的編輯合併成一個正確的。 –