tags:

views:

67

answers:

3
+3  Q: 

List set index c#

Hey there,

I am using a List construct to handle the sequence in which images are drawn in "OnPaint". Now if my images are re-ordered (e.g. "brought to front" or "..to back"), I'd need to reposition them in my List. I have trouble doing so, because List doesn't support a method similar to setIndex().

So what I am trying to do is basically:

    private List<BitmapWithProps> activeImages = new List<BitmapWithProps>();

    public void addActiveImage(BitmapWithProps image)
    {
        activeImages.Add(image);
    }

    public BitmapWithProps getActiveImage(int index)
    {
        return activeImages[index];
    }

    public void removeActiveImage(int index)
    {
        activeImages.RemoveAt(index);
    }

    public void removeActiveImage(BitmapWithProps item)
    {
        activeImages.Remove(item);
    }

    public void swapActiveImageIndex(int sourceIndex, int destIndex)
    {
        // what would the code look like in here if I were to swap
        // the 2nd item (1) with the 4th one (3) in a 5-item-List (0 - 4)
    }

I want to be able to swap an index.. sort of. I could "insert" a new item into the List at the index it should go to and assign the value and then delete the other "source". However it doesn't seem elegant in any way.

I'd be glad for any hints and please excuse me if I overlooked a thread - I did search though, before asking.

dS.

+3  A: 

What's inelegant about doing the steps you want to do? If you want to change something's position within a List (which is a vector style collection) then what you want to do is insert it at the new position and remove it from the old. Precisely what you are complaining about having to do.

If it really upsets you then write an extension method:

public static void MoveIndex<T>(this List<T> list, int srcIdx, int destIdx)
{
  if(srcIdx != destIdx)
  {
    list.Insert(destIdx, list[srcIdx]);
    list.RemoveAt(destIdx < srcIdx ? srcIdx + 1 : srcIdx);
  }
}

Edit: Oh, you just want to swap? Simpler (and more efficient) still:

public static void SwapItems<T>(this List<T> list, int idxX, int idxY)
{
  if(idxX != idxY)
  {
    T tmp = list[idxX];
    list[idxX] = list[idxY];
    list[idxY] = tmp;
  }
}
Jon Hanna
Thank you. I actually already thought about inserting/removing, but I thought there's a better way, like really .. swap or something. On the other hand - your method does precisely what I want to do. Now I only need to figure out how to add this method as an extension to the List :).Thank you +vote up.
Igor
I've added swapping too If those methods are put in a static class "visible" to the calling code, then `activeImages.MoveIndex(1, 3)` or `activeImages.SwapItems(1, 3)` will do the appropriate thing in C#3 or higher. C#2 or lower, you need to either get rid of the "this" and call them as static methods, or just do the same operations the methods have.
Jon Hanna
Note that the swap method should be preferred, because it is O(1) whereas List<T>.Insert and List<T>.RemoveAt are both O(n). They may have to move remaining elements in the list up and down, to keep the immediate list well-defined (but you actually just care about the final result).
Gnafoo
Ah. Thanks for this hint, Gnafoo. That's why I asked for help, because else I might have implemented a method that actually works, but is not "elegant" and thus needs more time to finish.
Igor
Yep, swapping beats moving where appropriate. However when not appropriate (you move the first item to the fourth position) then doing that by a series of swaps is also O(n) though for a smaller n, and has more expensive constants, so I'd go for the direct approach unless lists were likely to be very large, or the move in a loop.
Jon Hanna
Actually I am having trouble adding the code posted by Jon Hanna as an extension. I wanted the class "List" to have those methods. I defined a public static class within a new file in the same namespace.Now when I pasted the methods and wanted to use them where I used a List-object, they didn't appear. I recompiled and got strange errors saying that the type "T" could not be found and type "**System.Runtime.CompilerServices.ExtensionAttribute**" couldn't be found either.I am puzzled :/. How do I add those methods as an extension?
Igor
@divStar, there was a typo in the above, there should have been a <T> before the arguments for the method. I have editted to fix.
Jon Hanna
Jon, thank you very much again :). This was not the only problem though, but the other one seems to have been on my part. I've been compiling with .Net 3.0. However.. it kept giving me errors about "system.runtime.compilerservices.extensionattribute" and that I might've forgotten to add a reference to "System.Core" (which I of course have added). The only way to compile was to switch to v3.5 - then it worked like a charm. I thought that 3.0 supports extension methods, but something's wrong about that. .NET 3.5 works too for me, so thank you (same goes to all other posters too) for your help.
Igor
+1  A: 

Well, just performing a swap is easy:

BitmapWithProps source = activeImages[sourceIndex];
BitmapWithProps dest = activeImages[destIndex];
activeImages[destIndex] = source;
activeImages[sourceIndex] = dest;

But if you need to move one item and leave all other items in the same order with relation to each other, you should call RemoveAt followed by Insert. It won't be terribly efficient, but unless you've got a large list or you're doing this very often, it's unlikely to really cause you any problems.

Jon Skeet
A: 

public void swapActiveImageIndex(int sourceIndex, int destIndex) { var source = activeImages.Item[sourceIndex]; var dest = activeImages.Item[destIndex];

    activeImages.Item[sourceIndex] = dest;
    activeImages.Item[destIndex] = source;
}
gustavogb