我有一个这样的清单:
var query = Enumerable.Range(0, 999).Select((n, index) =>
{
if (index <= 333 || index >=777)
return 0;
else if (index <= 666)
return 1;
else
return 2;
});
那么,我能找到连续多少索引具有相同值吗?例如;
query[0]=query[1]=query[2]=query[3]... = 0, query[334] = 1, query[777]=query[778]... = 0.
前334个索引有0,所以第一个答案是333.另外最后223个索引有0,所以第二个答案是223 ..
如何找到这些及其索引?
提前致谢。
答案 0 :(得分:1)
使用here中的GroupConsecutive
扩展程序,您只需获取每个组的计数:
query.GroupConsecutive((n1, n2) => n1 == n2)
.Select(g => new {Number = g.Key, Count = g.Count()})
答案 1 :(得分:1)
您可以通过某个键为项目的连续分组创建扩展名:
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 }
]
答案 2 :(得分:0)
public static IEnumerable<int> GetContiguousCounts<T>(this IEnumerable<T> l, IEqualityComparer<T> cmp)
{
var last = default(T);
var count = 0;
foreach (var e in l)
{
if (count > 0 && !cmp.Equals(e, last))
{
yield return count;
count = 0;
}
count++;
last = e;
}
if (count > 0)
yield return count;
}
public static IEnumerable<int> GetContiguousCounts<T>(this IEnumerable<T> l)
{
return GetContiguousCounts(l, EqualityComparer<T>.Default);
}
static void Main(string[] args)
{
var a = new[] { 1, 2, 2, 3, 3, 3 };
var b = a.GetContiguousCounts();
foreach (var x in b)
Console.WriteLine(x);
}
对于简单的测试用例,它输出1,2,3。对于你的情况334,333,110,222(你问题中的最后一个值不是223,因为你只有999个元素,而不是1000个)。
答案 3 :(得分:0)
IEnuemrable<KeyValuePair<T, int>> RepeatCounter<T>(
IEnumerable<T> source,
IEqualityComparer<T> comparer = null)
{
var e = source.GetEnumerator();
if (!e.MoveNext())
{
yield break;
}
comparer = comparer ?? EqualityComparer<T>.Default;
var last = e.Current;
var count = 1;
while (e.MoveNext())
{
if (comparer.Equals(last, e.Current))
{
count++;
continue;
}
yield return new KeyValuePair<T, int>(last, count);
last = e.Current;
count = 1;
}
yield return new KeyValuePair<T, int>(last, count);
}
只列举一次序列,只在必要时分配变量。