Я хочу отсортировать этот список в .NET мой пример кода ниже - PullRequest
0 голосов
/ 02 ноября 2011
class Program
{


    static void Main(string[] args)
    {

        //Period 01 2008, Period 02 2008
        Series s1 = new Series { Text = "Period 01 2008", Value = "1"};
        Series s2 = new Series { Text = "Period 02 2008", Value = "2" };
        Series s3 = new Series { Text = "Period 03 2008", Value = "3" };

        Series s11 = new Series { Text = "Period 01 2009", Value = "1" };
        Series s21 = new Series { Text = "Period 02 2009", Value = "2" };
        Series s31 = new Series { Text = "Period 03 2009", Value = "3" };

        Series s12 = new Series { Text = "Period 01 2010", Value = "1" };
        Series s22 = new Series { Text = "Period 02 2010", Value = "2" };
        Series s32 = new Series { Text = "Period 03 2010", Value = "3" };

        List<Series> series = new List<Series> { s21, s31, s1, s12, s11, s2, s22, s3, s32 };


       // mySeries.ForEach(i => Console.WriteLine("Period {0} {1}",i.Period, i.Year));
        series.ForEach(i => Console.WriteLine(i.Text));

        Console.WriteLine("************************");

        series.OrderBy(i => i.Text);

        series.ForEach(i=> Console.WriteLine(i.Text));

    }

}


public class Series
{
    public string Text { get; set; }
    public string Value {get;set;}
}

По сути, я хочу, чтобы мой список был упорядочен по свойству Text класса Series.У меня есть обходной путь, разделив текст, но я ищу другой способ - используя IComparer может быть?

Упорядоченный список должен выглядеть примерно так:

Период 01 2008, Период 02 2008, Период 03 2008, Период 01 2009, Период 02 2009 ...

Обновление: определение класса Series изменить нельзя.

Ответы [ 5 ]

2 голосов
/ 02 ноября 2011

Метод расширения LINQ OrderBy возвращает новую отсортированную последовательность, с которой вы ничего не делаете.
Он не изменяет исходный список.

Вместо этого вы можете вызвать List<T>.Sort, который является сортировкой на месте, которая мутирует экземпляр List<T>:

series.Sort((a, b) => a.Text.CompareTo(b.Text));
0 голосов
/ 02 ноября 2011

Добавьте следующий сравнитель

public class SeriesTextComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string[] xparts = x.Split(' ');
        string[] yparts = y.Split(' ');

        if (xparts[2] == yparts[2])
        {
            if (Convert.ToInt32(xparts[1]) > Convert.ToInt32(yparts[1]))
            {
                return 1;
            }
            else if(Convert.ToInt32(xparts[1]) < Convert.ToInt32(yparts[1]))
            { 
                return -1;
            }
            else
            {
                return 0;
            }
        }
        else
        { 
        if (Convert.ToInt32(xparts[2]) > Convert.ToInt32(yparts[2]))
            {
                return 1;
            }
            else if(Convert.ToInt32(xparts[2]) < Convert.ToInt32(yparts[2]))
            { 
                return -1;
            }
            else
            {
                return 0;
            }
        }
    }
}

И измените две последние строки в вашем примере, как показано ниже

List<Series> sortedSeries =  series.OrderBy(i => i.Text, new SeriesTextComparer()).ToList();
sortedSeries.ForEach(i => Console.WriteLine(i.Text));
0 голосов
/ 02 ноября 2011

Хотя я бы сам этого не делал, это работает:

var sorted = series.OrderBy(s => s.Text.Split(' ')[2].Trim()).ThenBy(s => s.Text.Split(' ')[1].Trim());

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

В качестве альтернативы

Немного другой способ решения проблемысостоит в том, чтобы обернуть класс Series и предоставить больше полезных свойств (заявление об отказе, требуется лучший код синтаксического анализа!):

class BetterSeries
{
    public int Quarter {get;set;}
    public int Year {get;set;}
    public Series InnerSeries {get;private set;}

    public BetterSeries(Series s)
    {
        string[] parts = s.Text.Split(' ');
        Quarter = int.Parse(parts[1].Trim());
        Year = int.Parse(parts[2].Trim());
        InnerSeries = s;
    }

    public override string ToString()
    {
        return string.Format("Period {0} {1}", Quarter, Year);
    }
}

Это затем позволит вам упростить сортировку:

var sorted = series.OrderBy(s => s.Year).ThenBy(s => s.Quarter);

Это также означает, что вы не кодируете информацию в форматированный вывод данных, вы сохраняете сами данные, а затем добавляете код для форматирования вывода.

0 голосов
/ 02 ноября 2011

Я бы добавил DateTime свойство

Series s1 = new Series { 
    Text = "Period 01 2008", 
    Value = "1", 
    PeriodStart = new DateTime(2008, 01, 01) 
};

и заказ по нему:

series.OrderBy(i => i.PeriodStart).ForEach(i => Console.WriteLine(i.Text));

так что вы не соберете всех января вместе.

Кроме того, на вашу сортировку не будут влиять какие-либо изменения свойства Text, которое будет отображаться для отображения.

0 голосов
/ 02 ноября 2011

Обновить вторую последнюю строку в методе main до:

series = series.OrderBy(i => i.Text).ToList();

Счастливое кодирование

...