воскресенье, 25 августа 2013 г.

Linq. Изменение порядка сортировки OrderBy без IComparer.

[Linq. Change the sort order by using OrderBy without IComparer]

Метод-расширение OrderBy предоставляет собой отличное и эффективное средство для упорядочивания коллекций, например, по строковому ключу. Можно использовать версию метода без компаратора, тогда используется его стандартная общая реализация. Все же, для строк рекомендуется использовать специальный строковой компаратор StringComparer, с помощью которого можно учитывать регистр, язык и региональные параметры. Но даже его в некоторых, казалось бы, элементарных случаях может не хватать. Например тогда, когда среди ключей есть нулевые значения, эти элементы занимают самые первые позиции. А мне нужно было их откинуть назад. Что делать? Казалось бы, пришло время браться за реализацию своего компаратора! Но, оказывается, можно обойтись без нее, нужно лишь правильно выбирать ключ, т.е. "подменять" его нулевые значения значением "последнего ряда". У меня это "xxxxxxxxxx".

Итак, для наглядности на примере:

using System;
using System.Collections.Generic;
using System.Linq;

namespace BlogApp
{
    class Program
    {
        static void Main(string[] args) {

            List<MyData> myDataList = new List<MyData>();
            myDataList.Add(new MyData() { Val1 = "D", Val2 = "1" });
            myDataList.Add(new MyData() { Val1 = "B", Val2 = "2" });
            myDataList.Add(new MyData() { Val1 = "A", Val2 = "3" });
            myDataList.Add(new MyData() { Val1 = "D", Val2 = "4" });
            myDataList.Add(new MyData() { Val1 = null, Val2 = "5" });
            myDataList.Add(new MyData() { Val1 = null, Val2 = "6" });
            myDataList.Add(new MyData() { Val1 = "C", Val2 = "7" });
            myDataList.Add(new MyData() { Val1 = "B", Val2 = "8" });

            var res1 = myDataList.OrderBy(x => x.Val1);
            var res2 = myDataList.OrderBy(x => x.Val1 == null ? "xxxxxxxxxx" : x.Val1); // !!!!!!!

            Console.WriteLine("Result 1:");
            Console.WriteLine(String.Join(Environment.NewLine, res1.Select(x => String.Format("{0}:{1}", x.Val2, x.Val1))));
            Console.WriteLine();
            Console.WriteLine("Result 2:");
            Console.WriteLine(String.Join(Environment.NewLine, res2.Select(x => String.Format("{0}:{1}", x.Val2, x.Val1))));
            Console.ReadLine();
        }
    }

    public class MyData
    {
        public String Val1 { get; set; }
        public String Val2 { get; set; }
    }
}

Результат:

Комментариев нет: