Список сортировки на основе рассчитанного индекса свойств - PullRequest
0 голосов
/ 04 июля 2018

У меня следующий класс.

 public class Header
    {
        public long CombinedIndex { get; private set; }
        public int Key { get; set; } //Unique
        public bool IsRequired { get; set; }// True or false
        public DateTime? AvailableDate { get; set; } // null or date value
        public int Index { get; set; } // a number and can be same among other Header 

        public void CalculateCombinedIndex()
        {
            CombinedIndex = Key + (IsRequired ? 0 : 1) + Index + (AvailableDate ?? DateTime.MaxValue).Ticks;
        }
    }

Ожидается около 50 000 экземпляров. об этом в массиве. Мне нужно отсортировать их в следующем порядке:

  • Сначала на основе IsRequired
  • Тогда индекс
  • Тогда Доступная дата (значение даты близко к текущей дате)
  • Ключ (первичный ключ)

Имеет ли смысл говорить сумму всех этих значений свойства и получить уникальный номер, а затем только сортировать этот номер. Позже, список заголовков может быть преобразован в словарь, где Ключ CombinedIndex, и мой уже отсортированный массив может искать, что словарь по порядку я итерировал массив. Насколько эффективно и обещать это все выглядит?

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Я бы сделал это с LINQ:

var ordered = list
    .OrderByDescending(x => x.IsRequired)
    .ThenBy(x => x.Index)
    .ThenBy(x=> x.AvailableDate)
    .ThenBy(x=> x.Key);

Только в случае связей будет использовано следующее условие. Поэтому нет необходимости создавать комбинированный индекс, который очень затруднит изменение логики порядка и который в любом случае кажется нарушенным.

0 голосов
/ 04 июля 2018

Если вам нужно выполнить операции сравнения на основе прогнозируемого ключа данного типа, я считаю, что полезно иметь класс KeyComparer, который может создавать экземпляр IComparer<TSource> из делегата Func<TSource, TKey>. Это особенно хорошо работает с новым синтаксисом кортежей, представленным в C # 7. Вот пример результирующего синтаксиса:

// Create an IComparer<Header> instance based on your combined key.
var comparer = KeyComparer.Create((Header h) => (h.IsRequired, h.Index, h.AvailableDate, h.Key));

List<Header> headers = ...

// Sort the list using the combined key.
headers.Sort(comparer);

// Convert to a dictionary keyed by the combined key.
var dict = headers.ToDictionary(comparer.KeySelector);

А вот пример реализации класса. (Более подробное объяснение см. в моем блоге .)

public static class KeyComparer
{
    public static KeyComparer<TSource, TKey> Create<TSource, TKey>(
        Func<TSource, TKey> keySelector,
        IComparer<TKey> innerComparer = null)
    {
        return new KeyComparer<TSource, TKey>(keySelector, innerComparer);
    }
}

public class KeyComparer<TSource, TKey> : Comparer<TSource>
{
    protected internal KeyComparer(
        Func<TSource, TKey> keySelector,
        IComparer<TKey> innerComparer = null)
    {
        KeySelector = keySelector ?? throw new ArgumentNullException(nameof(keySelector));
        InnerComparer = innerComparer ?? Comparer<TKey>.Default;
    }

    public Func<TSource, TKey> KeySelector { get; }
    public IComparer<TKey> InnerComparer { get; }

    public override int Compare(TSource x, TSource y)
    {
        if (object.ReferenceEquals(x, y))
            return 0;
        if (x == null)
            return -1;
        if (y == null)
            return 1;

        TKey xKey = KeySelector(x);
        TKey yKey = KeySelector(y);
        return InnerComparer.Compare(xKey, yKey);
    }
}
0 голосов
/ 04 июля 2018

Просто внедрите IComparable , и вы можете использовать List.Sort ().

public class Header : IComparable
{
    public long CombinedIndex { get; private set; }
    public int Key { get; set; } //Unique
    public bool IsRequired { get; set; }// True or false
    public DateTime? AvailableDate { get; set; } // null or date value
    public int Index { get; set; } // a number and can be same among other Header 

    public void CalculateCombinedIndex()
    {
        CombinedIndex = Key + (IsRequired ? 0 : 1) + Index + (AvailableDate ?? DateTime.MaxValue).Ticks;
    }

    public int CompareTo(object obj)
    {
        if (obj == null) return 1;

        Header otherHeader = obj as Header;
        if (otherHeader != null)
        {
            if (this.IsRequired && !otherHeader.IsRequired)
                return 1;
            if (!this.IsRequired && otherHeader.IsRequired)
                return -1;
            if (this.Index > otherHeader.Index)
                return 1;
            if (this.Index < otherHeader.Index)
                return -1;
            //// ....
            return 0;
        }
        else
            throw new ArgumentException("Object is not a Temperature");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...