【问题标题】:Move item up in IEnumerable在 IEnumerable 中向上移动项目
【发布时间】:2010-03-12 10:24:37
【问题描述】:

我需要将 IEnumerable 中的项目向上移动,即将一个项目移到另一个之上。最简单的方法是什么?

这里问了一个类似的问题,但我没有一个通用列表,只有一个 IEnumerable:Generic List - moving an item within the list

【问题讨论】:

  • 将一个项目移到另一个之上是什么意思?是否要对元素进行排序?

标签: c# ienumerable


【解决方案1】:

正如@Brian 评论的那样,这个问题有点不清楚move an item in an IEnumerable<> up 的含义。

如果您想为单个项目重新排序 IEnumerable,那么下面的代码可能就是您要查找的代码。

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;
    }
}

【讨论】:

  • 这与我想要的很接近。谢谢
【解决方案2】:

你不能。 IEnumerable 仅用于遍历某些项目,而不是用于编辑项目列表

【讨论】:

  • 这并不意味着IEnumerable 的实现不允许这样做。
【解决方案3】:

您可以使用ToList() 扩展方法并使用您引用的问题的答案。例如

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

【讨论】:

  • 或者enumerable.OrderBy(e =&gt; e) 可以解决问题;-)
【解决方案4】:

我没有找到任何可以用 IEnumerable 做你想做的事。过去为特定类型的集合、列表、数组等开发了类似的东西,我觉得是时候更好地了解它了。所以我花了几分钟写了一个通用版本,可以应用于任何 IEnumerable

我做了一些基本的测试和参数检查,但绝不认为它们很全面。 鉴于该免责声明,让我们进入代码:

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);
    }
}

如您所见,MoveUp 和 MoveDown 基本上是 Swap 操作。使用 MoveUp 可以与前一个元素交换位置,使用 MoveDown 可以与下一个元素交换位置。 当然,这不适用于上移第一个元素或下移最后一个元素。

使用以下代码运行快速测试...

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);
        }
    }

...看起来一切正常。

我希望它至少可以作为您的起点。

【讨论】:

    【解决方案5】:

    我喜欢这种方法

        /// <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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 2020-10-29
      相关资源
      最近更新 更多