如果序列中的两个或多个元素在列表中具有相同的属性,我想识别并提取元素。 例如 我有一个清单 有一个名为Isvalid的文档属性 现在我想确定顺序中的两个或多个文档是否具有IsValid == true 假设结构是
IsValid = false
IsValid = true
IsValid = true
IsValid = false
IsValid = true
IsValid = false
我的查询应该只返回元素2和3,因为只有这两个是顺序的并且ISvalid = true 我该如何实现它?
答案 0 :(得分:1)
您可以编写一个简单的LINQ扩展方法:
public static IEnumerable<IEnumerable<TSource>>
ContinuouslyEqualSubSequences<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> func
) {
var e = source.GetEnumerator();
var currentSequence = default(List<TSource>);
var resultOfCurrentSequence = default(TResult);
if (e.MoveNext()) {
currentSequence = new List<TSource>() { e.Current };
resultOfCurrentSequence = func(e.Current);
}
while (e.MoveNext()) {
var currentResult = func(e.Current);
if(Object.Equals(resultOfCurrentSequence, currentResult)) {
currentSequence.Add(e.Current);
}
else {
if(currentSequence.Count > 1) {
yield return currentSequence;
}
currentSequence = new List<TSource>() { e.Current };
resultOfCurrentSequence = currentResult;
}
}
if (currentSequence.Count > 1) {
yield return currentSequence;
}
}
在
var sequence = new { 3, 4, 7, 8, 9, 2, 4, 6, 0, 1, 1, 17, 2, 3, 2, 20 };
var subsequences = sequence.ContinuouslyEqualSubSequences(x => x % 2);
我收回序列
2 4 6 0
1 1 17
2 20
正如预期的那样,因为我们在这里寻找奇数或偶数的连续子序列。
答案 1 :(得分:0)
您只需检查当前项是否有效以及前一项是否同时有效。这将捕获大多数情况,但如果尚未存储,则需要确保保留上一个项目。
类似下面的代码应该这样做。请注意,它是从内存中编写的,未经测试,而且我不是最有效的方法。
public List<Document> GetConsecutiveTrueDocs(List<Document> list)
{
var result = new List<Document>();
if(list.Count < 2)
return result;
for(int i = 1; i < list.Count; i++)
{
if(list[i].IsValid && list[i-1].IsValid)
{
if(!result.Contains(list[i-1]))
result.Add(list[i-1]);
result.Add(list[i]);
}
}
return result;
}
答案 2 :(得分:0)
这是一个相对简单的扩展方法,它接受一个源序列和一个函数,该函数告诉任何两个元素是否被认为是相等的,并返回一个元素序列:
public static IEnumerable<T> Consecutives<T>(this IEnumerable<T> source,
Func<T, T, bool> equals)
{
T last = default(T);
bool first = true;
bool returnedLast = false;
foreach (T current in source)
{
if (!first && equals(current, last))
{
if (!returnedLast)
yield return last;
returnedLast = true;
yield return current;
}
else
returnedLast = false;
first = false;
last = current;
}
}
如果您尝试
var sequence = new[] { 3, 4, 7, 8, 9, 2, 4, 6, 0, 1, 1, 17, 2, 3, 2, 20 };
var subsequences = sequence.Consecutives((x, y) => x % 2 == y % 2);
你会回来的:
2
4
6
0
1
1
17
2
20
如果您的序列没有重复,那么Raymond解决方案的扩展效率低下,但非常简单:
public static IEnumerable<T> Consecutives<T>(this IEnumerable<T> source,
Func<T, T, bool> equals)
{
return source.Zip(source.Skip(1), (x, y) => new[] { x, y })
.Where(d => equals(d[0], d[1]))
.SelectMany(d => d)
.Distinct();
}
答案 3 :(得分:0)
通过用自身的偏移版本压缩序列,可以将其简化为单行。
public static IEnumerable<Tuple<TSource,TSource>>
Consecutives<TSource>(this IEnumerable<TSource> source,
Func<TSource, TSource, bool> equals)
{
return source.Zip(source.Skip(1), (x, y) => Tuple.Create(x,y))
.Where(d => equals(d.Item1, d.Item2));
}