如何使用Linq / C#获取字典中当前和当前之后的项目?

时间:2010-12-02 11:21:34

标签: c# linq list foreach

我有一个项目字典,如果我选择一个项目,那么我将在上一个和下一个给出一个选项。我添加了一个代码示例,但我希望有更好/更快的方法来执行此操作,例如500个项目。

可能有LINQ选项吗?

我检查过枚举器,但它只有moveNext方法,无法设置当前值。

简单示例:

projectsDictionary

projectKeyValuePair中存在的Dictionary

var match = false;
var save = new KeyValuePair<ExtendedProjectLightPlan, Page>();
var before = new KeyValuePair<ExtendedProjectLightPlan, Page>();
var after = new KeyValuePair<ExtendedProjectLightPlan, Page>();
foreach (var p in projects)
{
    before = save;
    save = p;

    if (match)
    {
        after = p;
        break;
    }

    if (p.Key.Id == project.Key.Id)
    {
        match = true;
    }                
}

5 个答案:

答案 0 :(得分:16)

您是否尝试过使用IndexOf()ElementAt()方法?

    Int32 index = list1.IndexOf(item);
    var itemPrev = list1.ElementAt(index - 1);
    var itemNext = list1.ElementAt(index + 1);

答案 1 :(得分:16)

current”之前的项目:

items.TakeWhile(x => x != current).LastOrDefault();

current”之后的项目:

items.SkipWhile(x => x != current).Skip(1).FirstOrDefault();

适用于整数类型,但会在序列的末尾返回default(T)。将项目转换为Nullable<T>可能很有用,以便在第一个项目之前和最后一个项目之后返回null

答案 2 :(得分:14)

LINQ中没有内置任何内容,但您可以相当轻松地编写自己的...这是一个使用.NET 4中的Tuple的实现。它将为最初的序列返回n-2个项目有n个项目 - 但如果有必要,你可以调整它。

public IEnumerable<Tuple<T, T, T>> WithNextAndPrevious<T>
    (this IEnumerable<T> source)
{
    // Actually yield "the previous two" as well as the current one - this
    // is easier to implement than "previous and next" but they're equivalent
    using (IEnumerator<T> iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        T lastButOne = iterator.Current;
        if (!iterator.MoveNext())
        {
            yield break;
        }
        T previous = iterator.Current;
        while (iterator.MoveNext())
        {
            T current = iterator.Current;
            yield return Tuple.Create(lastButOne, previous, current);
            lastButOne = previous;
            previous = current;
        }
    }        
}

请注意,根据LukeH的回答,词典是无序的......但希望上述内容对您有所帮助。

答案 3 :(得分:5)

字典没有内在的排序,因此上一个和下一个项目的想法几乎是荒谬的。

答案 4 :(得分:1)

我同意关于词典排序的其他意见。但是,由于字典提供IEnumerable<KeyValuePair<K, V>>,至少有一个小论点可以说它们有某种顺序。无论如何,这是我的建议:

var ll = new LinkedList<ExtendedProjectLightPlan>();
var qs =
    from p in projects
    let node = ll.AddLast(p.Key)
    select new { Project = p, Node = node, };

var lookup = qs.ToDictionary(q => q.Project, q => q.Node);

var current = (ExtendedProjectLightPlan)null; //Whatever the current one is.

var previous = lookup[current].Previous.Value;
var next = lookup[current].Next.Value;

这使得从任何项目移动到上一个或下一个项目变得非常简单 - 而且速度非常快。 (虽然速度不应该是一个问题,因为这是用户界面,对吗?)