2014-11-17 4 views
0

Я хотел бы отсортировать список объектов, структура является Dictionary<Object, List<int>>рода словарь <объект Список <int>> C#

элементы в словаре будет

item_1, (2,2,3) 
item_2, (1,3,4) 
item_3, (2,3,4) 
item_4, (1,2) 

раз элементы сортируются они должны выглядеть как

item_4, 1,2 
item_2, 1,3,4 
item_1, 2,2,3 
item_3, 2,3,4 

так, по существу, я должен сортировать по первому элементу в списке, то второй пункт, затем 3-й элементы, что было бы простой способ реализация такого решения с использованием linq

+0

Являются ли предметы в «значении» вашего словаря обязательными для заказа или вы должны заказать их в то же время, когда хотите заказать ключи? Кроме того, вы хотите, чтобы словарь постоянно упорядочивался или просто заказывал его по требованию, когда вам нужно распечатывать его раз и навсегда. Если вы хотите, чтобы постоянный порядок вашего словаря был медленнее, и вам нужно будет использовать что-то вроде 'OrderedDictionary' –

+0

элементов в значении, необходимо сначала заказать его, его нужно заказывать по запросу – usr28765526

+1

Если заказывать эффект элементов 'List ', который хранится? Кроме того, если у меня есть 'item_5, (1,2,3)' какой элемент идет первым, Item_4 или Item_5? И, наконец, можете ли вы напомнить, что элементы в «List » пресечены? если это возможно, это облегчит проблему. –

ответ

4

Что вам нужно - это пользовательский сопоставитель, который может сравнивать последовательность значений на основе элементов в этой последовательности, а не на основе ссылки на саму последовательность (учитывая, что большинство последовательностей не переопределить поведение равенства по умолчанию). Это довольно просто:

public class SequenceComparer<T> : IComparer<IEnumerable<T>> 
{ 
    private IComparer<T> comparer; 
    public SequenceComparer(IComparer<T> comparer = null) 
    { 
     this.comparer = comparer ?? Comparer<T>.Default; 
    } 

    public int Compare(IEnumerable<T> x, IEnumerable<T> y) 
    { 
     using (var first = x.GetEnumerator()) 
     using (var second = y.GetEnumerator()) 
     { 
      while (true) 
      { 
       var hasFirst = first.MoveNext(); 
       var hasSecond = second.MoveNext(); 
       if (hasFirst && !hasSecond) 
        return 1; 
       if (hasSecond && !hasFirst) 
        return -1; 
       if (!hasFirst && !hasSecond) 
        return 0; 
       var comparison = comparer.Compare(first.Current, second.Current); 
       if (comparison != 0) 
        return comparison; 
      } 
     } 
    } 
} 

Вы можете заказать товары в вашей коллекции с помощью этой компаратора:

var query = dictionary.OrderBy(pair => pair.Value, new SequenceComparer<int>()); 

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

var query = dictionary.OrderBy(pair => pair.Value.OrderBy(x => x), 
    new SequenceComparer<int>()); 
+1

Какой вызов OrderBy вы вызываете, который принимает 'IEqualityComparer '? –

+0

@ScottChamberlain Справа, извините, схватил из-за неправильного источника. – Servy

+0

Вот это [.net скрипка] (https://dotnetfiddle.net/eecbZw). –

0

вы можете сортировать словарные значения в отдельном списке с помощью настраиваемого сравнения Метод:

static void Main() 
    { 
     var map = new Dictionary<object, IList<int>>(); 

     map.Add("item_1", new int[] { 2, 2, 4 }); 
     map.Add("item_2", new int[] { 1, 3, 4 }); 
     map.Add("item_3", new int[] { 2, 3, 4 }); 
     map.Add("item_4", new int[] { 1, 2}); 

     var list = new List<KeyValuePair<object, IList<int>>>(map); 

     list.Sort(CompareSequences); 


     foreach(var item in list) 
     { 
      Console.WriteLine("{0} ({1})", item.Key, string.Join<int>("," , item.Value)); 
     } 

    } 



    static int CompareSequences(KeyValuePair<object, IList<int>> left, 
     KeyValuePair<object, IList<int>> right) 
    { 
     int count = Math.Min(left.Value.Count, right.Value.Count); 

     for (int i = 0; i < count; ++i) 
     { 
      if (left.Value[i] < right.Value[i]) 
      { 
       return -1; 
      } 

      if (left.Value[i] > right.Value[i]) 
      { 
       return 1; 
      } 
     } 

     if (right.Value.Count > count) 
     { 
      return -1; 
     } 

     if (left.Value.Count > count) 
     { 
      return 1; 
     } 

     return 0; 
    } 

Одно различие с OrderBy() сортировка является то, что алгоритм сортировки в list.sort() не является стабильным. Но он использует меньше памяти и меньше временных объектов.

+0

Работает, но не использует Linq в соответствии с запросом OP (PS: здесь [.net скрипка] (https://dotnetfiddle.net/6OhT0w): :)). –

+0

Правда, я не заметил Линга в вопросе, спасибо, что указал мне. – alexm

+0

Тем не менее хороший альтернативный ответ. –

Смежные вопросы