Using the logic provided by the asker, here is a way to provide ElementBefore
and ElementAfter
access to any SortedSet
using extension methods:
public static class BeforeAfterExtension
{
//The true workhorse of the code!
public static T ElementBefore<T>(this SortedSet<T> mySet, T val, IComparer<T> comparer)
{
//we are getting the first element el such that it is before
//the provided value val. We must reverse the set because
//otherwise, the first element in the set is always the first
//to be less than the provided value.
return mySet.Reverse().FirstOrDefault(el => comparer.Compare(el, val) < 0);
}
//Contains all the actual logic
public static T ElementAfter<T>(this SortedSet<T> mySet, T val, IComparer<T> comparer)
{
//we are getting the first element el such that it is after
//the provided value val.
return mySet.FirstOrDefault(el => comparer.Compare(el, val) > 0);
}
//use the existing logic, but use the default comparer for the set
public static T ElementBefore<T>(this SortedSet<T> mySet, T val)
{
return ElementBefore(mySet, val, mySet.Comparer);
}
//use the existing logic, but use the default comparer for the set
public static T ElementAfter<T>(this SortedSet<T> mySet, T val)
{
return ElementAfter(mySet, val, mySet.Comparer);
}
//provide a condition that the element must already exist in the set
//Consider a set of strings containing only "apple" and "cat"
//without forcing the element to exist in the set, we could search for
//the element before "bear" and get "apple" even though "bear" is not
//in the set. Forcing the element to exist by setting mustExist=true
//would return null if the element is not there already
public static T ElementBefore<T>(this SortedSet<T> mySet, T val, bool mustExist, IComparer<T> comparer) {
{
if (mustExist)
{
if (mySet.Contains(val))
{
//take advantage of existing logic
return ElementBefore(mySet, val, comparer);
}
else
{
return null;
}
}
else
{
//take advantage of existing logic
return ElementBefore(mySet, val, comparer);
}
}
//provide a condition that the element must already exist in the set
//Consider a set of strings containing only "apple" and "cat"
//without forcing the element to exist in the set, we could search for
//the element after "bear" and get "cat" even though "bear" is not
//in the set. Forcing the element to exist by setting mustExist=true
//would return null if the element is not there already
public static T ElementBefore<T>(this SortedSet<T> mySet, T val, bool mustExist, IComparer<T> comparer) {
{
if (mustExist)
{
if (mySet.Contains(val))
{
//take advantage of existing logic
return ElementAfter(mySet, val, comparer);
}
else
{
return null;
}
}
else
{
//take advantage of existing logic
return ElementAfter(mySet, val, comparer);
}
}
//just use the default set comparer
public static T ElementBefore<T>(this SortedSet<T> mySet, T val, bool mustExist)
{
//take advantage of existing logic
return ElementBefore(mySet, val, mustExist, mySet.Comparer);
}
//just use the default set comparer
public static T ElementAfter<T>(this SortedSet<T> mySet, T val, bool mustExist)
{
//take advantage of existing logic
return ElementAfter(mySet, val, mustExist, mySet.Comparer);
}
}
There are some additional methods in there that allow the customization of the comparer used, and to require the element exists in the set.
Now all that is required is
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{
s = pastEntriesSS.ElementBefore(s);
}
else
{
s = pastEntriesSS.ElementAfter(s);
}
and this is extensible to sets containing any kind of object, not just strings