Reputation: 1435
Says I have this List : 1, 3, 5, 7, 9, 13
For example, given value is : 9, the previous item is 7 and the next item is 13
How can I achieve this using C#?
Upvotes: 48
Views: 143173
Reputation: 11
Maybe extend the class List :
public static class ListExtension
{
public static T Next<T>(this List<T> list, T elt)
{
int index = list.IndexOf(elt);
index = (index == list.Count - 1) ? 0 : index + 1;
return list[index];
}
public static T Prev<T>(this List<T> list, T elt)
{
int index = list.IndexOf(elt);
index = (index == 0) ? list.Count - 1 : index - 1;
return list[index];
}
}
to use the extend functions : List<anything> list;
list.Next(elt) give the element which follows elt and list.Prev(elt) the element which precedes elt
Upvotes: 1
Reputation: 45
Return null if the item is not found or if it is the last element in the list
List<string> fruits = new List<string> { "apple", "banana", "kiwi" };
var index = fruits.IndexOf("banana");
var nextFruit = index==-1 ?null : fruits.Skip(index+1).FirstOrDefault();
Upvotes: 0
Reputation: 1771
this is a fully circle list obtained combining @Thunder and @Melad answers:
private class CircularList<T> : List<T>
{
private int _currentIndex = 0;
public int CurrentIndex
{
get
{
if (_currentIndex > Count - 1) { _currentIndex = 0; }
if (_currentIndex < 0) { _currentIndex = Count - 1; }
return _currentIndex;
}
set => _currentIndex = value;
}
public int NextIndex
{
get
{
if (_currentIndex == Count - 1) return 0;
return _currentIndex + 1;
}
}
public int PreviousIndex
{
get
{
if (_currentIndex == 0) return Count - 1;
return _currentIndex - 1;
}
}
public T Next => this[NextIndex];
public T Previous => this[PreviousIndex];
public T MoveNext
{
get { _currentIndex++; return this[CurrentIndex]; }
}
public T MovePrevious
{
get { _currentIndex--; return this[CurrentIndex]; }
}
public T Current => this[CurrentIndex];
}
}
check git-repo with example here
Upvotes: 2
Reputation: 326
Also if you want compact solution with circular logic without creating new list you can use following code:
int nextNumber = list[(list.IndexOf(currentNumber) + 1) % list.Count];
int previousNumber = list[(list.IndexOf(currentNumber) - 1 + list.Count) % list.Count];
https://dotnetfiddle.net/PkP2Jy
Upvotes: 9
Reputation: 5530
Using LINQ in one line and with circular search:
Next of
YourList.SkipWhile(x => x != NextOfThisValue).Skip(1).DefaultIfEmpty( YourList[0] ).FirstOrDefault();
Previous of
YourList.TakeWhile(x => x != PrevOfThisValue).DefaultIfEmpty( YourList[YourList.Count-1]).LastOrDefault();
This is a working example (link to the fiddle)
List<string> fruits = new List<string> {"apple", "banana", "orange", "raspberry", "kiwi"};
string NextOf = "orange";
string NextOfIs;
NextOfIs = fruits.SkipWhile(x => x!=NextOf).Skip(1).DefaultIfEmpty(fruits[0]).FirstOrDefault();
Console.WriteLine("The next of " + NextOf + " is " + NextOfIs);
NextOf = "kiwi";
NextOfIs = fruits.SkipWhile(x => x!=NextOf).Skip(1).DefaultIfEmpty(fruits[0]).FirstOrDefault();
Console.WriteLine("The next of " + NextOf + " is " + NextOfIs);
string PrevOf = "orange";
string PrevOfIs;
PrevOfIs = fruits.TakeWhile(x => x!=PrevOf).DefaultIfEmpty(fruits[fruits.Count-1]).LastOrDefault();
Console.WriteLine("The prev of " + PrevOf + " is " + PrevOfIs);
PrevOf = "apple";
PrevOfIs = fruits.TakeWhile(x => x!=PrevOf).DefaultIfEmpty(fruits[fruits.Count-1]).LastOrDefault();
Console.WriteLine("The prev of " + PrevOf + " is " + PrevOfIs);
Upvotes: 41
Reputation: 935
To make it a kind of Circular list, try this:
public class NavigationList<T> : List<T>
{
private int _currentIndex = -1;
public int CurrentIndex
{
get
{
if (_currentIndex == Count)
_currentIndex = 0;
else if (_currentIndex > Count - 1)
_currentIndex = Count - 1;
else if (_currentIndex < 0)
_currentIndex = 0;
return _currentIndex;
}
set { _currentIndex = value; }
}
public T MoveNext
{
get { _currentIndex++; return this[CurrentIndex]; }
}
public T Current
{
get { return this[CurrentIndex]; }
}
}
Upvotes: 2
Reputation: 11016
I have implemented this by Inheriting the .Net List
public class NavigationList<T> : List<T>
{
private int _currentIndex = 0;
public int CurrentIndex
{
get
{
if (_currentIndex > Count - 1) { _currentIndex = Count - 1; }
if (_currentIndex < 0) { _currentIndex = 0; }
return _currentIndex;
}
set { _currentIndex = value; }
}
public T MoveNext
{
get { _currentIndex++; return this[CurrentIndex]; }
}
public T MovePrevious
{
get { _currentIndex--; return this[CurrentIndex]; }
}
public T Current
{
get { return this[CurrentIndex]; }
}
}
Using this becomes quite easy
NavigationList<string> n = new NavigationList<string>();
n.Add("A");
n.Add("B");
n.Add("C");
n.Add("D");
Assert.AreEqual(n.Current, "A");
Assert.AreEqual(n.MoveNext, "B");
Assert.AreEqual(n.MovePrevious, "A");
Upvotes: 13
Reputation: 46005
Approach with ElementOrDefault()
https://dotnetfiddle.net/fxVo6T
int?[] items = { 1, 3, 5, 7, 9, 13 };
for (int i = 0; i < items.Length; i++)
{
int? previous = items.ElementAtOrDefault(i - 1);
int? current = items.ElementAtOrDefault(i);
int? next = items.ElementAtOrDefault(i + 1);
}
Upvotes: 2
Reputation: 3193
This can be done using LinkedList<T>
List<int> intList = new List<int> { 1, 3, 5, 7, 9, 13 };
LinkedList<int> intLinkedList = new LinkedList<int>(intList);
Console.WriteLine("Next Value to 9 "+intLinkedList.Find(9).Next.Value);
Console.WriteLine("Next Value to 9 " +intLinkedList.Find(9).Previous.Value);
//Consider using dictionary for frequent use
var intDictionary = intLinkedList.ToDictionary(i => i, i => intLinkedList.Find(i));
Console.WriteLine("Next Value to 9 " + intDictionary[9].Next.Value);
Console.WriteLine("Next Value to 9 " + intDictionary[9].Previous.Value);
Console.Read();
Upvotes: 3
Reputation: 6278
Following may be helpful
int NextValue = 0;
int PreviousValue =0;
int index = lstOfNo.FindIndex(nd =>nd.Id == 9);
var Next = lstOfNo.ElementAtOrDefault(index + 1);
var Previous = lstOfNo.ElementAtOrDefault(index - 1);
if (Next != null)
NextValue = Next;
if (Previous != null)
PreviousValue = Previous;
Upvotes: 7
Reputation: 148180
You can use indexer to get element at desired index. Adding one to index will get you next and subtracting one from index will give you previous element.
int index = 4;
int prev = list[index-1];
int next = list[index+1];
You will have to check if next and previous index exists other wise you will get IndexOutOfRangeException exception. As List is zero based index so first element will have index 0
and second will have 1
and so on.
if(index - 1 > -1)
prev = list[index-1];
if(index + 1 < list.Length)
next = list[index+1];
Upvotes: 40
Reputation:
var index = list.IndexOf(9);
if (index == -1)
{
return; // or exception - whater, no element found.
}
int? nextItem = null; //null means that there is no next element.
if (index < list.Count - 1)
{
nextItem = list[index + 1];
}
int? prevItem = null;
if (index > 0)
{
prevItem = list[index - 1];
}
Upvotes: 3
Reputation: 608
List<int> listInts = new List<int>();
listInts.AddRange(new int[] { 1, 3, 5, 7, 9, 13 });
int index = listInts.IndexOf(3); //The index here would be "1"
index++; //Check first if the index is in the length
int element = listInts[index]; //element = 5
Upvotes: 8
Reputation: 101711
int index = list.IndexOf(9); // find the index of the given number
// find the index of next and the previous number
// by taking into account that
// the given number might be the first or the last number in the list
int prev = index > 0 ? index - 1 : -1;
int next = index < list.Count - 1 ? index + 1 : -1;
int nextItem, prevItem;
// if indexes are valid then get the items using indexer
// otherwise set them to a temporary value,
// you can also use Nullable<int> instead
nextItem = prev != -1 ? list[prev] : 0;
prevItem = next != -1 ? list[next] : 0;
Upvotes: 4