2010-03-12 2 views
3

Мне нужно переместить элемент в IEnumerable <> вверх, то есть переместить один элемент над другим. Каков самый простой способ сделать это?Переместить элемент вверх в IEnumerable

Аналогичный вопрос здесь просили, но у меня нет общего списка только IEnumerable <>: Generic List - moving an item within the list

+3

Что вы имеете в виду перемещение элемента над другим? Вы хотите отсортировать элементы? –

ответ

7

Как отметил @ Брайан вопрос немного неясно, какие 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; 
    } 
} 
+0

Это близко к тому, что я искал. спасибо – Nina

1

Вы можете использовать метод расширение ToList() и использовать ответ от вопроса вы ссылочный. например

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

Или, возможно, 'enumerable.OrderBy (e => e)' будет делать трюк ;-) – Steven

3

Вы не можете. IEnumerable только для итерации через некоторые элементы, а не для редактирования списка элементов.

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

Как вы можете видеть, 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); 
     } 
    } 

... похоже, все работает хорошо.

Я надеюсь, что он служит хотя бы отправной точкой для вас.

0

Мне нравится этот подход

/// <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); 
     } 
    } 
} 
Смежные вопросы