Andrew Rayner
Andrew Rayner

Reputation: 424

LINQ List<> Moving Elements up and down

Would it be possible to tell me the best way of moving elements in a List<> up and down.

For example I have a class called Building and Building has a list of Rooms objects List<Room>. The rooms are added to the building by name, but I am using this structure to generate a tree view. The user has the option to move a room up and down within a building.

I was trying to use .Reverse(index, count) but this didn't seem to do anything:

// can this item actually be moved up (is it at the first position in it's current parent?)
if (moveDirection == MoveDirection.UP)
{
    int roomIndex = parentBuilding.Rooms.IndexOf(room);

    if (roomIndex == 0)
    {
        return;
    }
    else
    {
        // move this room up.                            
        parentBuilding.Rooms.Reverse(roomIndex, 1);
    }
}

Upvotes: 3

Views: 14776

Answers (6)

LukeHennerley
LukeHennerley

Reputation: 6444

Create a list extension. Call as List<T>.Move(1, MoveDirection.Up).

public static class ListExtensions
{
    public static void Move<T>(this IList<T> list, int iIndexToMove, 
        MoveDirection direction)
    {

        if (direction == MoveDirection.Up)
        {
            var old = list[iIndexToMove - 1];
            list[iIndexToMove - 1] = list[iIndexToMove];
            list[iIndexToMove] = old;
        }
        else
        {
            var old = list[iIndexToMove + 1];
            list[iIndexToMove + 1] = list[iIndexToMove];
            list[iIndexToMove] = old;
        }
    }
}

public enum MoveDirection
{
    Up,
    Down
}

Things to consider

  • Exception handling - what if you are trying to move the bottom element down or top element up? You will get an index out of range because you can't move these up or down.

  • You could improve this and prevent handling exception by extending functionality to moving the top element to the bottom element and bottom element down to the top element etc.

Upvotes: 11

Dave Bish
Dave Bish

Reputation: 19646

Just do a swap:

int roomIndex = parentBuilding.Rooms.IndexOf(room);

if (roomIndex == 0)
{
    return;
}
else
{
    // move this room up.                            
    var temp = parentBuilding.Rooms[index-1];
    parentBuilding.Rooms[index-1] = parentBuilding.Rooms[index];
    parentBuilding.Rooms[index] = temp;
}

Upvotes: 4

Leri
Leri

Reputation: 12535

Personally, I'd make extension method:

static void Swap<TSource>(this IList<TSource> source, int fromIndex, int toIndex)
{
    if (source == null)
        throw new ArgumentNullExcpetion("source");

    TSource tmp = source[toIndex];
    source[toIndex] = source[fromIndex];
    source[fromIndex] = tmp;
}

Usage:

if (moveDirection == MoveDirection.UP)
{
    int roomIndex = parentBuilding.Rooms.IndexOf(room);

    if (roomIndex == 0)
    {
        return;
    }
    else
    {
        // move this room up.                            
        parentBuilding.Rooms.Swap(roomIndex, roomIndex - 1);
    }
}

Upvotes: 1

Toon Casteele
Toon Casteele

Reputation: 2579

try this:

int newIndex = whateverIndexYouWantItAt;

int oldIndex = parentBuilding.Rooms.IndexOf(room);
var item = parentBuilding.Rooms[oldIndex];

list.RemoveAt(oldIndex);

if (newIndex > oldIndex) newIndex--; 

parentBuilding.Rooms.Insert(newIndex, item);

Upvotes: 0

Jon
Jon

Reputation: 437474

Swapping places with the room that used to be above should do it:

int roomIndex = parentBuilding.Rooms.IndexOf(room);

if (roomIndex == 0)
{
    return;
}

var wasAbove = parentBuilding.Rooms[roomIndex - 1];
parentBuilding.Rooms[roomIndex - 1] = room;
parentBuilding.Rooms[roomIndex] = wasAbove;

That said, I 'm not sure that this is the best object model for the situation; it's not clear that the order of rooms in the list plays a role, and it's also not clear how a room can be "moved up" -- what does that mean?

It might be better to have a RoomPlacement class that aggregates a room and enough information to locate it, and work with that instead.

Upvotes: 0

TKharaishvili
TKharaishvili

Reputation: 2099

How about using SortedDictionary<int, Room> instead of a list. You could store an index in as a Key of the Dictionary and just swap the values when needed.

Upvotes: 0

Related Questions