Move item up in IEnumerable

I need to move an element in IEnumerable <> up, which moves one element above another. What is the easiest way to do this?

A similar question was asked here, but I do not have a general list, only IEnumerable <>: General list - moving an item in a list

+3
source share
5 answers

As @Brian noted, the question is a bit unclear as to what it means move an item in an IEnumerable<> up.

If you want to reorder IEnumerable for a single element, then the code below may be what you are looking for.

public static IEnumerable<T> MoveUp<T>(this IEnumerable<T> enumerable, int itemIndex)
{
    int i = 0;

    IEnumerator<T> enumerator = enumerable.GetEnumerator();
    while (enumerator.MoveNext())
    {
        i++;

        if (itemIndex.Equals(i))
        {
            T previous = enumerator.Current;

            if (enumerator.MoveNext())
            {
                yield return enumerator.Current;
            }

            yield return previous;

            break;
        }

        yield return enumerator.Current;
    }

    while (enumerator.MoveNext())
    {
        yield return enumerator.Current;
    }
}
+7
source

. IEnumerable , .

+2

ToList() , . .

var list = enumerable.ToList();
//do stuff from other answer, and then convert back to enumerable if you want
var reorderedEnumerable = list.AsEnumerable();
+1

, IEnumerable <T> . , , .., , . , , IEnumerable <T> .

, . , , :

static class Enumerable {
    public static IEnumerable<T> MoveDown<T>(this IEnumerable<T> source, int index) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        if (index == array.Length - 1) {
            return source;
        }
        return Swap<T>(array, index, index + 1);
    }

    public static IEnumerable<T> MoveDown<T>(this IEnumerable<T> source, T item) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        int index = Array.FindIndex(array, i => i.Equals(item));
        if (index == -1) {
            throw new InvalidOperationException();
        }
        if (index == array.Length - 1) {
            return source;
        }
        return Swap<T>(array, index, index + 1);
    }

    public static IEnumerable<T> MoveUp<T>(this IEnumerable<T> source, int index) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        if (index == 0) {
            return source;
        }
        return Swap<T>(array, index - 1, index);
    }

    public static IEnumerable<T> MoveUp<T>(this IEnumerable<T> source, T item) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        int index = Array.FindIndex(array, i => i.Equals(item));
        if (index == -1) {
            throw new InvalidOperationException();
        }
        if (index == 0) {
            return source;
        }
        return Swap<T>(array, index - 1, index);
    }

    public static IEnumerable<T> Swap<T>(this IEnumerable<T> source, int firstIndex, int secondIndex) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        return Swap<T>(array, firstIndex, secondIndex);
    }

    private static IEnumerable<T> Swap<T>(T[] array, int firstIndex, int secondIndex) {
        if (firstIndex < 0 || firstIndex >= array.Length) {
            throw new ArgumentOutOfRangeException("firstIndex");
        }
        if (secondIndex < 0 || secondIndex >= array.Length) {
            throw new ArgumentOutOfRangeException("secondIndex");
        }
        T tmp = array[firstIndex];
        array[firstIndex] = array[secondIndex];
        array[secondIndex] = tmp;
        return array;
    }

    public static IEnumerable<T> Swap<T>(this IEnumerable<T> source, T firstItem, T secondItem) {
        if (source == null) {
            throw new ArgumentNullException("source");
        }
        T[] array = source.ToArray();
        int firstIndex = Array.FindIndex(array, i => i.Equals(firstItem));
        int secondIndex = Array.FindIndex(array, i => i.Equals(secondItem));
        return Swap(array, firstIndex, secondIndex);
    }
}

As you can see, MoveUp and MoveDown are basically Swap operations. With MoveUp, you change positions with the previous element, and with MoveDown you change positions with the next element. Of course, this does not apply to moving the first element or moving through the last element.

Performing a quick test using the code below ...

class Program {
    static void Main(string[] args) {
        int[] a = { 0, 2, 1, 3, 4 };
        string[] z = { "Zero", "Two", "One", "Three", "Four" };
        IEnumerable<int> b = Enumerable.Swap(a, 1, 2);
        WriteAll(b);
        IEnumerable<int> c = Enumerable.MoveDown(a, 1);
        WriteAll(c);
        IEnumerable<int> d = Enumerable.MoveUp(a, 2);
        WriteAll(d);
        IEnumerable<int> f = Enumerable.MoveUp(a, 0);
        WriteAll(f);
        IEnumerable<int> g = Enumerable.MoveDown(a, 4);
        WriteAll(g);
        IEnumerable<string> h = Enumerable.Swap(z, "Two", "One");
        WriteAll(h);
        var i = z.MoveDown("Two");
        WriteAll(i);
        var j = z.MoveUp("One");
        WriteAll(j);
        Console.WriteLine("Press any key to continue...");
        Console.Read();
    }

    private static void WriteAll<T>(IEnumerable<T> b) {
        foreach (var item in b) {
            Console.WriteLine(item);
        }
    }

... everything seems to be working fine.

I hope this at least serves as a starting point for you.

+1
source

I like this approach

    /// <summary>
/// Extension methods for <see cref="System.Collections.Generic.List{T}"/>
/// </summary>
public static class ListExtensions
{
    public static void MoveForward<T>(this List<T> list, Predicate<T> itemSelector, bool isLastToBeginning)
    {
        Ensure.ArgumentNotNull(list, "list");
        Ensure.ArgumentNotNull(itemSelector, "itemSelector");

        var currentIndex = list.FindIndex(itemSelector);

        // Copy the current item
        var item = list[currentIndex];

        bool isLast = list.Count - 1 == currentIndex;

        if (isLastToBeginning && isLast)
        {
            // Remove the item
            list.RemoveAt(currentIndex);

            // add the item to the beginning
            list.Insert(0, item);
        }
        else if (!isLast)
        {
            // Remove the item
            list.RemoveAt(currentIndex);

            // add the item at next index
            list.Insert(currentIndex + 1, item);
        }
    }

    public static void MoveBack<T>(this List<T> list, Predicate<T> itemSelector, bool isFirstToEnd)
    {
        Ensure.ArgumentNotNull(list, "list");
        Ensure.ArgumentNotNull(itemSelector, "itemSelector");

        var currentIndex = list.FindIndex(itemSelector);

        // Copy the current item
        var item = list[currentIndex];

        bool isFirst = 0 == currentIndex;

        if (isFirstToEnd && isFirst)
        {
            // Remove the item
            list.RemoveAt(currentIndex);

            // add the item to the end
            list.Add(item);             
        }
        else if (!isFirstToEnd)
        {
            // Remove the item
            list.RemoveAt(currentIndex);

            // add the item to previous index
            list.Insert(currentIndex - 1, item);
        }
    }
}
0
source

Source: https://habr.com/ru/post/1736631/


All Articles