This is a general array question but, for my case, it is a list of strings.
Given: [a, b, c, d, e, f, g, h] and an item inside of the collection, say f.
Output: [f, g, h, a, b, c, d, e]
I can use substring methods or things like .take and .skip. But are there any cleaner alternatives like using linq or something else I might be unaware of?
edit: Okay, I apologize that I did not write question correctly. When I say LINQ, I meant something involving lambda expressions? Thanks for your comments. I will just stick with take and skip.
CodePudding user response:
The Take()
and Skip()
methods are part of the LINQ. I do not see how you could rearrange the items inside the list via LINQ without using these methods.
List<string> list = new List<string>() { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
string character = "f";
int i = list.IndexOf(character);
if (i != -1)
{
list = list.Skip(i).Concat(list.Take(i)).ToList();
}
You could also use List
specific methods like below
List<string> list = new List<string>() { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
string character = "f";
int i = list.IndexOf(character);
if (i != -1)
{
var sublist = list.GetRange(i, list.Count - i);
list.RemoveRange(i, list.Count - i);
list.InsertRange(0, sublist);
}
CodePudding user response:
another possibility
var newlist = new List<string>(oldList.Count);
newList.Add("f");
newList.AddRange(oldList.Where(x=>x!="f"));
less efficeint since it keeps looking at the elements even after its found the target one, but the code is simple
CodePudding user response:
If you don't mind creating a new List
or array, you can use an extension method (for IEnumerable<T>
) to rotate the items and then create the collection you want.
// num - return items starting with numth item and wrapping around
// e.g. rotate items so that numth item is first
public static IEnumerable<T> Rotate<T>(this IEnumerable<T> items, int num) {
if (num > 0)
if (items is IList<T> itemList) {
for (int j1 = 0; j1 < itemList.Count; j1)
yield return itemList[(j1 num) % itemList.Count];
}
else
using (var itemsEnum = items.GetEnumerator()) {
var q = new Queue<T>();
while (itemsEnum.MoveNext() && num-- > 0)
q.Enqueue(itemsEnum.Current);
do {
yield return itemsEnum.Current;
} while (itemsEnum.MoveNext());
while (q.Count > 0)
yield return q.Dequeue();
}
}
With this extension method, you can do
var ans = src.Rotate(src.IndexOf("f")).ToList(); // or .ToArray()
If you want to do this with no additional object creation, you can use this answer instead.