I have the following list of distinct strings:
"A"
"B"
"C"
If I want the item after A, I get B. After B, I get C. After C, I get A. Currently I have the following code, but for some reason it feels to me that there is a better way to go about this (maybe?).
private string GetNext(IList<string> items, string curr)
{
if (String.IsNullOrWhitespace(curr))
return items[0];
var index = items.IndexOf(curr);
if (index == -1)
return items[0];
return (index + 1 == items.Count) ? items[0] : items[index + 1];
}
I'm definitely open to a LINQ-esque way of doing this as well :)
The solution you have is functionally correct but it's performance leaves a little to be desired. Typically when dealing with a list style structure you would expect that GetNext
would return a result in O(1) time yet this solution is O(N).
public sealed class WrappingIterator<T> {
private IList<T> _list;
private int _index;
public WrappingIterator<T>(IList<T> list, int index) {
_list = list;
_index = index;
}
public T GetNext() {
_index++;
if (_index == _list.Count) {
_index = 0;
}
return _list[_index];
}
public static WrappingIterator<T> CreateAt(IList<T> list, T value) {
var index = list.IndexOf(value);
return new WrappingIterator(list, index);
}
}
The initial call to CreateAt
is O(N) here but subsequent calls to GetNext
are O(1).
IList<string> list = ...;
var iterator = WrappingIterator<string>.CreateAt(list, "B");
Console.WriteLine(iterator.GetNext()); // Prints C
Console.WriteLine(iterator.GetNext()); // Prints A
Console.WriteLine(iterator.GetNext()); // Prints B
I think maybe you can change the line
return (index + 1 == items.Count) ? items[0] : items[index + 1];
for something like
return items[(index + 1) % items.Count];
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