views:

865

answers:

5

Say I have 3 strings in a List (e.g. "1","2","3").

Then i want to reorder them to place "2" in position 1 (e.g. "2","1","3").

I am using this code (setting indexToMoveTo to 1):

listInstance.Remove(itemToMove);
listInstance.Insert(indexToMoveTo, itemToMove);

This seems to work BUT I am occasionally getting strange results; sometimes the order is incorrect or items from the list are getting deleted!

Any ideas? and does List guarantee order?

Related:

Does a List guarantee that items will be returned in the order they were added?

+13  A: 

The List<> class does guarantee ordering - things will be retained in the list in the order you add them, including duplicates, unless you explicitly sort the list.

You might be getting odd results from your code if you're moving the item later in the list, as your Remove() will move all of the other items down one place before the call to Insert().

Can you boil your code down to something small enough to post?

Bevan
+5  A: 

As Bevan said, but keep in mind, that the list-index is 0-based. If you want to move an element to the front of the list, you have to insert it at index 0 (not 1 as shown in your example).

M4N
A: 

This is the code I have for moving an item down one place in a list:

if (this.folderImages.SelectedIndex > -1 && this.folderImages.SelectedIndex < this.folderImages.Items.Count - 1)
{
    string imageName = this.folderImages.SelectedItem as string;
    int index = this.folderImages.SelectedIndex;

    this.folderImages.Items.RemoveAt(index);
    this.folderImages.Items.Insert(index + 1, imageName);
    this.folderImages.SelectedIndex = index + 1;
 }

and this for moving it one place up:

if (this.folderImages.SelectedIndex > 0)
{
    string imageName = this.folderImages.SelectedItem as string;
    int index = this.folderImages.SelectedIndex;

    this.folderImages.Items.RemoveAt(index);
    this.folderImages.Items.Insert(index - 1, imageName);
    this.folderImages.SelectedIndex = index - 1;
}

folderImages is a ListBox of course so the list is a ListBox.ObjectCollection, not a List<T>, but it does inherit from IList so it should behave the same. Does this help?

Of course the former only works if the selected item is not the last item in the list and the latter if the selected item is not the first item.

ChrisF
+4  A: 

I asked a similar question a while back that you may find useful:

Does a List<T> guarantee that items will be returned in the order they were added?

Kev
+5  A: 

Here's 4 items, with their index.

0  1  2  3
K  C  A  E

You want to move K to between A and E -- you might think position 3. You have be careful about your indexing here, because after the remove, all the indexes get updated.

So you remove item 0 first, leaving

0  1  2
C  A  E

Then you insert at 3

0  1  2  3
C  A  E  K

To get the correct result, you should have used index 2. To make things consistent, you will need to send to (indexToMoveTo-1) if indexToMoveTo > indexToMove, e.g.

bool moveUp = (listInstance.IndexOf(itemToMoveTo) > indexToMove);
listInstance.Remove(itemToMove);
listInstance.Insert(indexToMoveTo, moveUp ? (itemToMoveTo - 1) : itemToMoveTo);

This may be related to your problem. Note my code is untested!

EDIT (moved from comment): Alternatively, you could Sort with a custom comparer (IComparer) if that's applicable to your situation.

Joel Goodwin
Didn't read Bevan's response carefully enough, I've just covered the ground he has.
Joel Goodwin