C# 在IEnumerable中向上移动项

C# 在IEnumerable中向上移动项,c#,ienumerable,C#,Ienumerable,我需要将IEnumerable中的一个项向上移动,也就是将一个项移到另一个项之上。最简单的方法是什么 这里问了一个类似的问题,但我没有一个通用列表,只有一个IEnumerable:您可以使用ToList()扩展方法,并使用您引用的问题的答案。e、 g var list = enumerable.ToList(); //do stuff from other answer, and then convert back to enumerable if you want var reorderedE

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


这里问了一个类似的问题,但我没有一个通用列表,只有一个IEnumerable:

您可以使用
ToList()
扩展方法,并使用您引用的问题的答案。e、 g

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

正如@Brian所评论的,这个问题有点不清楚在IEnumerable中向上移动一个项目意味着什么

如果您想为单个项重新排序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;
    }
}
公共静态IEnumerable MoveUp(此IEnumerable可枚举,int itemIndex)
{
int i=0;
IEnumerator枚举器=可枚举的.GetEnumerator();
while(枚举数.MoveNext())
{
i++;
if(itemIndex.Equals(i))
{
T previous=当前枚举数;
if(枚举数.MoveNext())
{
产生返回枚举数。当前;
}
以前的收益率;
打破
}
产生返回枚举数。当前;
}
while(枚举数.MoveNext())
{
产生返回枚举数。当前;
}
}

你不能。IEnumerable只是对某些项目进行迭代,而不是编辑项目列表

我没有找到任何可以满足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);
    }
}
静态类可枚举{
公共静态IEnumerable向下移动(此IEnumerable源,int索引){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
if(index==array.Length-1){
返回源;
}
返回交换(数组、索引、索引+1);
}
公共静态IEnumerable向下移动(此IEnumerable源,T项){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
int index=Array.FindIndex(Array,i=>i.Equals(item));
如果(索引==-1){
抛出新的InvalidOperationException();
}
if(index==array.Length-1){
返回源;
}
返回交换(数组、索引、索引+1);
}
公共静态IEnumerable MoveUp(此IEnumerable源,int索引){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
如果(索引==0){
返回源;
}
返回交换(数组,索引-1,索引);
}
公共静态IEnumerable MoveUp(此IEnumerable源,T项){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
int index=Array.FindIndex(Array,i=>i.Equals(item));
如果(索引==-1){
抛出新的InvalidOperationException();
}
如果(索引==0){
返回源;
}
返回交换(数组,索引-1,索引);
}
公共静态IEnumerable交换(此IEnumerable源、int firstIndex、int secondIndex){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
返回交换(数组、第一索引、第二索引);
}
私有静态IEnumerable交换(T[]数组,int firstIndex,int secondIndex){
if(firstIndex<0 | | firstIndex>=array.Length){
抛出新ArgumentOutOfRangeException(“firstIndex”);
}
if(secondIndex<0 | | secondIndex>=array.Length){
抛出新ArgumentOutOfRangeException(“secondIndex”);
}
T tmp=数组[firstIndex];
数组[firstIndex]=数组[secondIndex];
数组[secondIndex]=tmp;
返回数组;
}
公共静态IEnumerable交换(此IEnumerable源、T firstItem、T secondItem){
if(source==null){
抛出新的ArgumentNullException(“源”);
}
T[]数组=source.ToArray();
int firstIndex=Array.FindIndex(数组,i=>i.Equals(firstItem));
int secondIndex=Array.FindIndex(数组,i=>i.Equals(secondItem));
返回交换(数组、第一索引、第二索引);
}
}
如您所见,MoveUp和MoveDown基本上是交换操作。使用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);
        }
    }
类程序{
静态void Main(字符串[]参数){
int[]a={0,2,1,3,4};
字符串[]z={“零”、“二”、“一”、“三”、“四”};
IEnumerable b=可枚举.Swap(a,1,2);
书面文件(b);
IEnumerable c=可枚举的向下移动(a,1);
书面(c);
IEnumerable d=可枚举的移动(a,2);
书面答覆(d);
IEnumerable f=可枚举的移动(a,0);
书面(f);
IEnumerable g=可枚举的向下移动(a,4);
书面形式(g);
IEnumerable h=可枚举的.Swap(z,“二”,“一”);
书面(h);
var i=z.向下移动(“两”);
书面(i);
var j=z.MoveUp(“一”);
书面(j);
Console.WriteLine(“按任意键继续…”);
Console.Read();
}
私有静态void WriteAll(IEnumerable b){
foreach(b中的var项目){
控制台写入线(项目);
}
}
    /// <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);
        }
    }
}