tags:

views:

362

answers:

3

Is there a LINQ way to swap the position of two items inside a list<T>?

+8  A: 

Maybe someone will think of a clever way to do this, but you shouldn't. Swapping two items in a list is inherently side-effect laden but LINQ operations should be side-effect free. Thus, just use a simple extension method:

static class IListExtensions {
    public static void Swap<T>(
        this IList<T> list,
        int firstIndex,
        int secondIndex
    ) {
        if (list == null) {
            throw new ArgumentNullException("list");
        }
        if (firstIndex < 0 || firstIndex >= list.Count) {
            throw new ArgumentOutOfRangeException("firstIndex");
        }
        if (secondIndex < 0 || secondIndex >= list.Count) {
            throw new ArgumentOutOfRangeException("secondIndex");
        }
        if (firstIndex == secondIndex) {
            return;
        }
        T temp = list[firstIndex];
        list[firstIndex] = list[secondIndex];
        list[secondIndex] = temp;
    }
}
Jason
Side effects? Can you elaborate?
Tony
+1 for argument checking and an extension method
plinth
By Side Effects he mean they alter the list and possibly the items in the list - as opposed to just querying data which would not modify anything
saret
A: 

If order matters, you should keep a property on the "T" objects in your list that denotes sequence. In order to swap them, just swap the value of that property, and then use that in the .Sort(comparison with sequence property)

Chad
That's if you can conceptually agree that your T has an inherent "order", but not if you want it to be sorted in an arbitrary fashion without inherent "order", such as in a UI.
Dave Van den Eynde
+5  A: 

Check the answer from Marc from http://stackoverflow.com/questions/552731/c-good-best-implementation-of-swap-method.

static void Swap(IList<int> list, int indexA, int indexB)
{
    int tmp = list[indexA];
    list[indexA] = list[indexB];
    list[indexB] = tmp;
}

which can be linq-i-fied like

static IList<T> Swap<T>(this IList<T> list, int indexA, int indexB)
{
    T tmp = list[indexA];
    list[indexA] = list[indexB];
    list[indexB] = tmp;
    return list;
}

var lst = new List<int>() { 8, 3, 2, 4 };
lst = lst.Swap(1, 2);
Jan Jongboom
Downvote reason?
Jan Jongboom
This is not LINQified.
Jason