在IEnumerable中向上移动项目

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

这里有一个类似的问题,但我没有通用列表只有IEnumerable : Generic List – 在列表中移动一个项目

正如@Brian评论的那样,关于move an item in an IEnumerable<> up意味着什么有点不清楚。

如果您想为单个项目重新排序IEnumerable,那么下面的代码应该是您正在寻找的。

 public static IEnumerable MoveUp(this IEnumerable enumerable, int itemIndex) { int i = 0; IEnumerator 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只是迭代一些项目,而不是编辑项目列表

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

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

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

我做了一些基本的测试和参数检查,但绝不认为它们是复杂的 。 鉴于免责声明,让我们来看看代码:

 static class Enumerable { public static IEnumerable MoveDown(this IEnumerable source, int index) { if (source == null) { throw new ArgumentNullException("source"); } T[] array = source.ToArray(); if (index == array.Length - 1) { return source; } return Swap(array, index, index + 1); } public static IEnumerable MoveDown(this IEnumerable 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(array, index, index + 1); } public static IEnumerable MoveUp(this IEnumerable source, int index) { if (source == null) { throw new ArgumentNullException("source"); } T[] array = source.ToArray(); if (index == 0) { return source; } return Swap(array, index - 1, index); } public static IEnumerable MoveUp(this IEnumerable 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(array, index - 1, index); } public static IEnumerable Swap(this IEnumerable source, int firstIndex, int secondIndex) { if (source == null) { throw new ArgumentNullException("source"); } T[] array = source.ToArray(); return Swap(array, firstIndex, secondIndex); } private static IEnumerable Swap(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 Swap(this IEnumerable 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 b = Enumerable.Swap(a, 1, 2); WriteAll(b); IEnumerable c = Enumerable.MoveDown(a, 1); WriteAll(c); IEnumerable d = Enumerable.MoveUp(a, 2); WriteAll(d); IEnumerable f = Enumerable.MoveUp(a, 0); WriteAll(f); IEnumerable g = Enumerable.MoveDown(a, 4); WriteAll(g); IEnumerable 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(IEnumerable b) { foreach (var item in b) { Console.WriteLine(item); } } 

……看起来一切运转良好。

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

我喜欢这种方法

  ///  /// Extension methods for  ///  public static class ListExtensions { public static void MoveForward(this List list, Predicate 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(this List list, Predicate 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); } } }