我有一个自定义类型的 IEnumerable。 (我从 SelectMany 得到的)
我在那个 IEnumerable 中也有一个项目 (myItem),我希望 IEnumerable 中的上一个和下一个项目。
目前,我正在做这样的事情:
var previousItem = myIEnumerable.Reverse().SkipWhile(
i => i.UniqueObjectID != myItem.UniqueObjectID).Skip(1).FirstOrDefault();
我可以通过简单地省略 .Reverse
来获得下一个项目。
或者,我可以:
int index = myIEnumerable.ToList().FindIndex(
i => i.UniqueObjectID == myItem.UniqueObjectID)
然后使用 .ElementAt(index +/- 1)
获取上一个或下一个项目。
- 这两个选项哪个更好?
- 是否有更好的选择?
“更好”包括性能(内存和速度)和可读性的结合;可读性是我最关心的问题。
最佳答案
首先
"Better" includes a combination of performance (memory and speed)
一般来说你不能两者兼得,经验法则是,如果你优化速度,它会消耗内存,如果你优化内存,它会消耗你的速度。
有一个更好的选择,它在内存和速度方面都表现良好,并且可以以可读的方式使用(我对函数名称不满意,但是,FindItemReturningPreviousItemFoundItemAndNextItem
是一个有点含糊)。
所以,看起来是时候使用自定义查找扩展方法了,比如 . . .
public static IEnumerable<T> FindSandwichedItem<T>(this IEnumerable<T> items, Predicate<T> matchFilling)
{
if (items == null)
throw new ArgumentNullException("items");
if (matchFilling == null)
throw new ArgumentNullException("matchFilling");
return FindSandwichedItemImpl(items, matchFilling);
}
private static IEnumerable<T> FindSandwichedItemImpl<T>(IEnumerable<T> items, Predicate<T> matchFilling)
{
using(var iter = items.GetEnumerator())
{
T previous = default(T);
while(iter.MoveNext())
{
if(matchFilling(iter.Current))
{
yield return previous;
yield return iter.Current;
if (iter.MoveNext())
yield return iter.Current;
else
yield return default(T);
yield break;
}
previous = iter.Current;
}
}
// If we get here nothing has been found so return three default values
yield return default(T); // Previous
yield return default(T); // Current
yield return default(T); // Next
}
如果您需要多次引用项目,您可以将此结果缓存到列表中,但它会返回找到的项目,前面是前一个项目,然后是下一个项目。例如
var sandwichedItems = myIEnumerable.FindSandwichedItem(item => item.objectId == "MyObjectId").ToList();
var previousItem = sandwichedItems[0];
var myItem = sandwichedItems[1];
var nextItem = sandwichedItems[2];
如果它是第一个或最后一个项目,则返回的默认值可能需要根据您的要求进行更改。
希望这对您有所帮助。
关于c# - 使用 LINQ 获取 IEnumerable 中的上一个和下一个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8759849/