I want to iterate through some list items in such a way that I would start from a specific position and then go left from it, after that go right from it.
In other words, something like this:
var items = new List<string>() { "Item1", "Item2", "Item3", "Item4", "Item5" };
string item = "Item3";
int index = items.IndexOf(item);
for (int i = index; i >= 0; i--)
yield return items[i];
for (int i = index 1; i < items.Count; i )
yield return items[i];
The result is: Item3
, Item2
, Item1
, Item4
, Item5
Is there a way to achieve this, but using only one for-loop?
Or is there some kind of conditional direction in LINQ?
CodePudding user response:
You could use the ternary if and some simple arithmetic on the index to achieve this.
for (int i = 0; i < items.Count; i )
yield return i <= index ? items[index - i] : items[i];
Result:
Item3
Item2
Item1
Item4
Item5
CodePudding user response:
You cannot use two returns at the same time using one loop, but it is possible to fetch data.
for (int i = index; i >= 0; i--)
{
string answer1 = items[i]; //2,1,0
if(items.Count - i < items.Count)
string answer2 = items[items.Count - i]; // 3,4
}
CodePudding user response:
Something like this perhaps, with tuple deconstruction:
var items = new List<string>() { "Item1", "Item2", "Item3", "Item4", "Item5" };
string item = "Item3";
int index = items.IndexOf(item);
for ((int i, int j) = (index, 0); j < items.Count; i--, j ){
if(i>=0){
yield return items[i];
} else {
yield return item[j];
}
}
CodePudding user response:
Another solution using the pythonic way would be by generating the sequence of indexes using Enumerable.Range
.
foreach (int i in Enumerable.Range(0, index 1).Reverse().Union(Enumerable.Range(index 1, items.Count - index - 1)))
yield return items[i];
But in terms of performance and maintainability, I would go with your existing solution using two separate for-loops.
In terms of making the intent of your code more clearly, I would go with items.Take(3).Reverse().Concat(items.Skip(3))
as it says directly what will happen.