2013-06-15 25 views
0

Рассмотрим 4 (скажем, до 100) экземпляров класса A в списке, который имеет заказ свойства int.Самый простой способ упорядочить последовательность

a0.Order is 0 
a1.Order is 1 
a2.Order is 2 
a3.Order is 3 

Теперь сделать заказ должен быть изменен таким образом, что a0 вставляется перед a3 (или любого индекса в списке. - может быть начало, конец или середину)

Результат должен быть таким :

a0.Order is 2 
a1.Order is 0 
a2.Order is 1 
a3.Order is 3 

Примечание: это список, а фактический физический порядок списка не имеет значения, только изменения свойств.

Количество элементов не меняется, просто «заказ».

Что такое самый простой способ достичь этого?

+1

Определение Лучший? Быстрее, быстрее программировать, проще всего понять? – Joppe

+0

Насколько велик список? Небольшие списки (даже меньше нескольких тысяч) или даже немного большие списки, которые не меняют все это часто, вероятно, не стоит оптимизировать для эффективности алгоритма. –

+0

Макс. 100 предметов. Легче всего понять. –

ответ

3

Свойство Order не должно быть целым числом, но десятичное. Вы можете легко изменить значение, а затем отсортировать его для извлечения элементов в произвольном порядке. Новое значение - это средняя точка между предыдущими и следующими значениями.

P.S. Затем вам нужно изменить свойство Order для элементов (ов) в списке, который вы хотите переместить.

+0

Да, это был ответ - как только я начал использовать десятичную таблицу, сортировка была довольно простой. –

+0

разве это не очень ограниченное пространство? При первом перемещении у вас уже будет 1 десятичный (т. Е. Между 2 и 3: 2,5), со вторым шагом вы можете получить 2,75, затем 2,875 и т. Д. У вас быстро закончится цифра. –

+0

@DirkBoer: Не могли бы вы разобраться, как быстро? Если у вас закончились цифры, просто пересчитайте их все. –

1

Если вы можете позволить себе я бы пронумеровать их с промежутками между ними:

a0.Order is 10 
a1.Order is 20 
a2.Order is 30 
a3.Order is 40 

Таким образом, вы можете просто перезаказа, выбирая номер в болтливости.

a0.Order is 35 
a1.Order is 20 
a2.Order is 30 
a3.Order is 40 

После некоторых итераций у вас может не быть gabs, оставшихся в какой-либо точке вставки. С 100 пунктами вы можете просто сбросить все номера заказов, чтобы снова получить равные габсы.

+0

Возможно, но не совсем то, что я искал. –

2

Вы могли бы сделать что-то вроде этого:

void MoveAndUpdateOrder(List<A> list, A item, int positionToInsert) 
{ 
    // Order elements 
    var ordered_list = list.OrderBy(a => a.Order).ToList(); 

    // Remove and insert at the proper position 
    ordered_list.Remove(item); 
    ordered_list.Insert(positionToInsert, item); 

    // Update the Order properties according to it's current index 
    for (int i = 0; i < ordered_list.Count; i++) 
     ordered_list[i].Order = i; 
} 

А потом называют это так:

var a0 = new A { Order = 0 }; 
var a1 = new A { Order = 1 }; 
var a2 = new A { Order = 2 }; 
var a3 = new A { Order = 3 }; 

var list = new List<A> 
{ 
    a0, a1, a2, a3 
}; 

MoveAndUpdateOrder(list, a0, 2); 
1

Мы должны различать перемещение элемента вверх (до конца) или вниз (в начало списка). Определим два номера заказа i и k где i < k.

Переместить элемент i вверх k:
Приказы ниже i и выше k не затрагиваются.
Заказы i+1 ... k уменьшены на 0, а i - k.

Переместить элемент k вниз к i:
Приказы ниже i и выше k не затрагиваются.
Заказы i ... k-1 увеличены на 1, а k - i.

Перемещение вверх:

A moving = list.Where(a => a.Order == i); 
foreach (A x in list.Where(a => a.Order > i && a.Order <= k) 
{ 
    x.Order--; 
} 
moving.Order = k; 

Перемещение вниз:

A moving = list.Where(a => a.Order == k); 
foreach (A x in list.Where(a => a.Order >= i && a.Order < k) 
{ 
    x.Order++; 
} 
moving.Order = i; 
0

Не могли бы вы просто держать элементы в списке и означают Order свойство из physcial порядка элементов в списке?

Дан Item класса без свойство заказа, например, так:

class Item 
{ 
    public readonly string Value; 

    public Item(string value) 
    { 
     Value = value; 
    } 

    public override string ToString() 
    { 
     return Value; 
    } 
} 

Вы могли бы написать простой класс коллекции для Items, который имеет метод Move(), чтобы вы переместить элемент из одного индекса к другому :

class Items: IEnumerable<Item> 
{ 
    private readonly List<Item> _items = new List<Item>(); 

    public void Add(Item item) 
    { 
     _items.Add(item); 
    } 

    public int Count 
    { 
     get { return _items.Count; } 
    } 

    public void Move(int oldIndex, int newIndex) 
    { 
     Item item = _items[oldIndex]; 
     _items.RemoveAt(oldIndex); 
     _items.Insert(newIndex, item); 
    } 

    IEnumerator<Item> IEnumerable<Item>.GetEnumerator() 
    { 
     return _items.GetEnumerator(); 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return _items.GetEnumerator(); 
    } 
} 

Вы можете использовать Items так:

var items = new Items 
{ 
    new Item("a0"), 
    new Item("a1"), 
    new Item("a2"), 
    new Item("a3") 
}; 

// ... 

items.Move(0, 2); // Move the item at index 0 to index 2. 

Затем, когда вы нуждаетесь в Order можно синтезировать из физического порядка входящих в список, как так:

var orderedItems = items.Select((item, index) => new { Item = item, Order = index}); 
0

Я написал алгоритм для вас, что использует сортировку и сбор LinkedList:

using System; 
using System.Collections.Generic; 

namespace OrderExample { 

    public class A { 
     public int Order { get; set; } 
    } 

    public class Program { 

     // Change order so that a is ordered between b and c. 
     public static void SetOrder(List<A> list, A a, A b, A c) { 
      list.Sort((x, y) => x.Order.CompareTo(y.Order)); 
      var linkedList = new LinkedList<A>(list); 
      var bNode = linkedList.Find(b); 
      if (bNode != null) { 
       linkedList.Remove(a); 
       linkedList.AddAfter(bNode, a); 
       var i = 0; 
       foreach (var value in linkedList) { 
        value.Order = i++; 
       }     
      } 
     } 

     static void Main() { 
      var a0 = new A {Order = 0}; 
      var a1 = new A {Order = 1}; 
      var a2 = new A {Order = 2}; 
      var a3 = new A {Order = 3}; 
      var list = new List<A> {a0, a1, a2, a3}; 

      SetOrder(list, a0, a2, a3); 
      foreach (var a in list) { 
       Console.Out.WriteLine(a.Order); 
      } 
      Console.ReadKey(); 
     } 
    } 
} 
Смежные вопросы