How do i move a list object at the end of the list while shifting back the others?
First of all i must say i have spent all my day searching my answer before i posted this question here. The closest answer i get is here but some of the answers didnt work for me while others are too complicated for me to understand.
Let me explain clearly what i want to achieve: For simplicity lets think i have a list that consists of "6" objects. I randomly select an index in the list, lets say, myList[2]. Then i want this object to go at the end of the list meaning its index value is now 5. Also i want to re-arrange the untouched objects to get the same size of list without empty index value. After all these steps it should like this:
At the moment my code is this:
public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
if ((oldIndex == newIndex) || (0 > oldIndex) || (oldIndex >= list.Count) || (0 > newIndex) ||
(newIndex >= list.Count)) return;
// local variables
var i = 0;
T tmp = list[oldIndex];
for (i = oldIndex+1; i < newIndex; i++)
{
list[i] = list[i - 1];
}
list[newIndex] = tmp;
}
However, as you can predict it doesnt work. Debug.DrawLine to gameobjects in this list shows me when i move the items through the list with my code leave me two objects one myList[0] and one myList[5] which i added. The other lines disappears after.
public List<T> $$anonymous$$oveToLast(List<T> myList, int index)
{
var temp = myList[index];
int x = 0;
for (int i = 0; i < myList.Count; i++)
{
if (i != index)
{
myList[x++] = myList[i];
}
}
myList[myList.Length -1] = temp;
return myList;
}
Pretty sure this should work, just thought it for off the top of my head, but it looks solid.
As a note, you'll have to replace the Generic T with your class type, as you cannot return generic lists like that.
In your suggesting i dont achieve what i want because your loop looks like this:
At the end, i override both my first and last index where their previous values are lost.
Did you actually try it? I don't see the issue here, it moves all elements down except the one you are saving for last, then moves the intended element into the last position of the array. While still keeping the count and order. Also you are storing the myList[index] BEFORE the loop, so it doesn't matter what's in the index after the loop, then you assign the stored value to the last index...
In my example, by using X, you skip over the element you are moving but without increasing X if it's the element, therefore the next element AFTER the one you're moving, moves into the index of the one you are moving. So your example is 100% wrong, because myList[4] would = myList[5] and myList[5] would = myList[2]
Answer by azilvl · Apr 09, 2019 at 09:15 PM
this should do it.
public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
List<T> tempList = new List<T>(list);
T item = list[oldIndex];
tempList.RemoveAt(oldIndex);
list.Clear();
int j = 0;
for (int i = 0; i < tempList.Count + 1; i++)
{
list.Add(i == newIndex ? item : tempList[j]);
j += i == newIndex ? 0 : 1;
}
}
edit: turns out lists already have an Insert method so this can be achived with a lot less effort.
public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
T item = list[oldIndex];
list.RemoveAt(oldIndex);
list.Insert(newIndex, item);
}
except that allocates ram for another list when it can be achieved with the existing list.
Not sure you need the tempList or the loop. Just list.Remove(oldIndex) then list.InsertAt(newIndex, item);. I think you have to subtract 1 if new is greater than old, to account for the indexes moving. Actually "C# move element in list" on StackExchange has the short way, with an explanation.
@Owen-Reynolds yeah didn't know there was a list.insert().