I have a dictionary of projects and if I select a project then I will give an option previous and next. I have added a code example but I hope there is a better / faster way to do this e.g. for 500 projects.
Is there maybe a LINQ option or something?
I have checked Enumerator but it only has a moveNext
method and can't set the current.
Quick example:
projects
is a Dictionary
.
project
is a KeyValuePair
that exists in the 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;
}
}
Item before 'current
':
items.TakeWhile(x => x != current).LastOrDefault();
Item after 'current
':
items.SkipWhile(x => x != current).Skip(1).FirstOrDefault();
Works well for integral types but will return default(T)
at the ends of the sequence. It might be useful to cast the items to Nullable<T>
so that before the first item, and after the last item return null
instead.
Have you tried using IndexOf()
and ElementAt()
methods??
Int32 index = list1.IndexOf(item);
var itemPrev = list1.ElementAt(index - 1);
var itemNext = list1.ElementAt(index + 1);
There's nothing built into LINQ to do this, but you could write your own fairly easily... here's an implementation which uses Tuple
from .NET 4. It will return n-2 items for a sequence which originally has n items - but you could adjust that if necessary.
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;
}
}
}
Note that as per LukeH's answer, dictionaries are unordered... but hopefully the above will help you anyway.
Dictionaries have no intrinsic ordering, so the idea of previous and next items is pretty much nonsensical.
I agree with the other comments with regard to ordering in dictionaries. But since dictionaries offer IEnumerable<KeyValuePair<K, V>>
there is, at least, a small argument to say they have some sort of order. Anyway, here's my suggestion:
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;
This should make it very simple to move from any project to the previous or next one - and it will be very very fast. (Although speed shouldn't be an issue since this is for UI, right?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With