假设我有一个包含类型对象的列表Value.Value有一个Name属性:
private List<Value> values = new List<Value> {
new Value { Id = 0, Name = "Hello" },
new Value { Id = 1, Name = "World" },
new Value { Id = 2, Name = "World" },
new Value { Id = 3, Name = "Hello" },
new Value { Id = 4, Name = "a" },
new Value { Id = 5, Name = "a" },
};
Run Code Online (Sandbox Code Playgroud)
现在我想获得所有"重复"值的列表(name属性与前一个元素的name属性相同的元素).
在这个例子中,我想要一个包含两个元素"world"和"a"(id = 2和5)的列表.
这个事件可以用linq吗?当然,我可以这样做.像这样:
List<Value> tempValues = new List<Value>();
String lastName = String.Empty();
foreach (var v in values)
{
if (v.Name == lastName) tempValues.Add(v);
lastName = v.Name;
}
Run Code Online (Sandbox Code Playgroud)
但是因为我想在更复杂的环境中使用这个查询,所以可能有一个"linqish"解决方案.
这些行中不会有任何内置的东西,但如果你经常需要它,你可以推出一些定制但相当通用的东西:
static IEnumerable<TSource> WhereRepeated<TSource>(
this IEnumerable<TSource> source)
{
return WhereRepeated<TSource,TSource>(source, x => x);
}
static IEnumerable<TSource> WhereRepeated<TSource, TValue>(
this IEnumerable<TSource> source, Func<TSource, TValue> selector)
{
using (var iter = source.GetEnumerator())
{
if (iter.MoveNext())
{
var comparer = EqualityComparer<TValue>.Default;
TValue lastValue = selector(iter.Current);
while (iter.MoveNext())
{
TValue currentValue = selector(iter.Current);
if (comparer.Equals(lastValue, currentValue))
{
yield return iter.Current;
}
lastValue = currentValue;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
foreach (Value value in values.WhereRepeated(x => x.Name))
{
Console.WriteLine(value.Name);
}
Run Code Online (Sandbox Code Playgroud)
您可能想要考虑如何处理三元组等 - 目前除了第一个之外的所有内容都将被生成(与您的描述相符),但这可能不太正确.