在IEnumerable的使用LINQ获得一个和下一个项目 [英] Get previous and next item in a IEnumerable using LINQ

查看:132
本文介绍了在IEnumerable的使用LINQ获得一个和下一个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个IEnumerable一个自定义类型。 (我已经从得到的SelectMany)

I have an IEnumerable of a custom type. (That I've gotten from a SelectMany)

我也有在这IEnumerable的,我希望从IEnumerable的前一个和下一个项目一个项目(myItem)。

I also have an item (myItem) in that IEnumerable that I desire the previous and next item from the IEnumerable.

目前,我正在做所需的是这样的:

Currently, I'm doing the desired like this:

var previousItem = myIEnumerable.Reverse().SkipWhile( 
    i => i.UniqueObjectID != myItem.UniqueObjectID).Skip(1).FirstOrDefault();



我可以通过简单的ommitting .Reverse

的,我可以:

int index = myIEnumerable.ToList().FindIndex( 
    i => i.UniqueObjectID == myItem.UniqueObjectID)

然后用 .ElementAt(+/-指数1)来获取上一个或下一个项目。

and then use .ElementAt(index +/- 1) to get the previous or next item.


  1. 这是两个选项?

  2. 之间的更好是否有更好的选择可用?

更好包括的性能组合(内存和速度)和可读性;可读性是我的首要问题。

"Better" includes a combination of performance (memory and speed) and readability; with readability being my primary concern.

推荐答案

首先

更好包括的性能组合(内存和速度)

"Better" includes a combination of performance (memory and speed)

在一般不能兼得,经验法则是,如果你优化的速度,它会花费内存,如果你优化内存,它会花费你的速度。

In general you can't have both, the rule of thumb is, if you optimise for speed, it'll cost memory, if you optimise for memory, it'll cost you speed.

有一个更好的选择,这两个内存和速度方面表现良好,并能以可读的方式来使用(我不是很高兴与函数名,但是, FindItemReturningPreviousItemFoundItemAndNextItem 是一个拗口位)。

There is a better option, that performs well on both memory and speed fronts, and can be used in a readable manner (I'm not delighted with the function name, however, FindItemReturningPreviousItemFoundItemAndNextItem is a bit of a mouthful).

所以,它看起来像它的时候了一个自定义查找扩展方法,有点像。 。

So, it looks like it's time for a custom find extension method, something like . . .

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
}

您可以缓存的这个结果列表,如果你需要提及的项目超过一次,但它返回找到的项目,由前项前面,随后将下列项目。 。例如

You can cache the result of this to a list if you need to refer to the items more than once, but it returns the found item, preceded by the previous item, followed by the following item. e.g.

var sandwichedItems = myIEnumerable.FindSandwichedItem(item => item.objectId == "MyObjectId").ToList();
var previousItem = sandwichedItems[0];
var myItem = sandwichedItems[1];
var nextItem = sandwichedItems[2];



默认值返回,如果它是第一个或最后一个项目可能需要根据您的需求来改变。

The defaults to return if it's the first or last item may need to change depending on your requirements.

希望这有助于。

这篇关于在IEnumerable的使用LINQ获得一个和下一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆