我有一个复杂的谜题要给你
我有一种情况,我有一个对象集合,我要返回给定类型的对象之间的所有对象
我还有一个对象,我知道它在集合中,我也知道它在两个对象之间
所以我想返回一组位于给定类型的两个对象之间的周围对象(和self(。
这有意义吗?
以下是我迄今为止的一个示例:
此集合中有两个集合
此查询返回第一组对象,但我不检查已知对象是否在此集合内,并且不会继续搜索集合。
class Between { }
class Known{}
var bob = new Known();
var objs = new object[]
{
"Outside",
new Between(),
"Inside",
bob,
"Inside",
new Between(),
"Outside",
new Between(),
"Inside",
"Inside",
new Between(),
"Outside"
};
var objsBetween = objs
.SkipWhile(x => x.GetType() != typeof(Between))
.Skip(1)
.TakeWhile(x => x.GetType() != typeof(Between)).ToList();
//...Result
/*
{
"Inside",
bob,
"Inside"
}
*/
你明白我想做什么吗
Linq是最好的方法吗?还是应该使用recersive函数?
感谢
如果你真的想使用LINQ,你可以让它与Aggregate((一起使用,但我可能只会创建一个迭代器方法,因为我认为代码更清晰:
IEnumerable<object> GetBetween(IEnumerable<object> items, Type betweenType)
{
bool between = false;
foreach (object item in items)
{
if (item.GetType() == betweenType)
between = !between;
else if (between)
yield return item;
}
}
然后你可以做:
var objsBetween = GetBetween(objs, typeof(Between)).ToList();
我想出了一个解决方案,我从MoreLinq窃取了TakeUntil
代码,并创建了另一个递归扩展方法
事实证明,对于我的需求,仅仅检查类型是不够的,我需要一个谓词:
static class Extensions
{
public static IEnumerable<TSource> TakeUntil<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
return _(); IEnumerable<TSource> _()
{
for (int i=0;i< source.Count();i++)
{
yield return source.ElementAt(i);
if (predicate(source.ElementAt(i), i))
yield break;
}
}
}
public static List<List<T>> SetsBetween<T>(this List<T> collection, Func<T, bool> betweenPredicate, List<List<T>> toReturn = null)
{
if (toReturn == null)
{
toReturn = new List<List<T>>();
}
var set = collection.SkipWhile(x => !betweenPredicate(x))
.TakeUntil((x, i) => (i > 0) && betweenPredicate(x))
.ToList();
toReturn.Add(set.Skip(1).SkipLast(1).ToList());
collection.RemoveAll(x => set.Contains(x));
if (collection.Any(x => betweenPredicate(x)))
{
collection.SetsBetween(betweenPredicate, toReturn);
}
return toReturn;
}
然后像这样使用:
var bob = new Person();
var objs = new List<object>()
{
"Outside",
new Between(),
"Inside",
bob,
"Inside",
new Between(),
"Outside",
new Between(),
"Not this",
"Not this either",
new Between(),
"Outside"
};
var sets = objs.SetsBetween(x => x.GetType() == typeof(Between));
var bobSet = sets.Where(x => x.Contains(bob)).SelectMany(x => x).ToList();
所以,如果有人想知道的话,我之所以这么做是因为我想为Markdig解析的Markdowwn文档中的每个元素创建CSS选择器
因此,最终此代码将允许我获得两个HTMLBlock
之间的元素的nth-of-type
。