Есть ли лучший способ заказать IEnumerable, чтобы соответствовать произвольному порядку? - PullRequest
3 голосов
/ 17 февраля 2012

Я сталкивался с этой проблемой на работе, и хотя у меня есть решение, я не могу не чувствовать, что есть более элегантный способ. Использование List.IndexOf () кажется мне немного хакерским.

Я должен отсортировать коллекцию BreakdownItems по кредитному рейтингу. Кредитные рейтинги не следуют в алфавитном порядке, поэтому я воспринимал их как произвольный, нелогичный порядок.

IEnumerable<BreakdownItem> unsortedCreditRatings = new List<BreakdownItem>
        {
            new BreakdownItem{ Name = "CCC", Weight=20d},
            new BreakdownItem{ Name = "AA", Weight=20d},
            new BreakdownItem{ Name = "AAA", Weight=10d},
            new BreakdownItem{ Name = "B", Weight=50d},
        };

        var sortOrder = new List<string> 
    { "AAA", "AA", "A", "BBB", "BB", "B", "CCC", "below CCC" };

        var sortedRatingBreakdown = unsortedCreditRatings
           .OrderBy(item => sortOrder.IndexOf(item.Name));

Ответы [ 3 ]

5 голосов
/ 17 февраля 2012

Можете ли вы сделать кредитный рейтинг перечислением вместо строки?Затем вы можете присвоить этим значениям перечисления правильный порядок сортировки.

3 голосов
/ 17 февраля 2012

Как я уже упоминал в своем комментарии выше, наличие нескольких кредитных рейтингов в виде строки может вызвать проблемы с целостностью данных, вместо этого я бы переместил их в enum, например:

public enum CreditRatings
{
     AAA,
     AA,
     A,
     BBB,
     BB,
     B,
     CCC,
     etc
}

И вместо этого вы сохраняете это в своем BreakdownItem, вы можете сделать:

var sortedRatingBreakdown = unsortedCreditRatings.OrderBy(item => item.Rating);

Если вы должны сохранить их как string и не можете использовать enum, вы можете рассмотреть возможность использования Dictionary<string, int> или чего-то подобного для хранения своего заказа, чтобы вы по крайней мере получить O (1) время поиска:

var ratingOrders = new Dictionary<string,int>
    {
        { "AAA", 1 },
        { "AA", 2 },
        { "A", 3 },
        etc...
    };

Тогда вы можете заказать по результатам словаря:

var sortedRatingBreakdown = unsortedCreditRatings.OrderBy(item => ratingOrders[item.Name]);
2 голосов
/ 17 февраля 2012

Enumerable.Join сохраняет порядок первой (или внешней) последовательности.Если вы не заинтересованы в подходе enum, вы можете использовать его без необходимости явно OrderBy.

var orderedRatings = from item in sortOrder
                     join rating in unsortedCreditRatings
                     on item equals rating.Name
                     select rating;
...