9

私は次のソートを使用しています:

var query = _cityRepository.GetAll(
               .OrderBy(item => item.RowKey.Substring(0, 4))
               .ThenBy(item => item.ShortTitle)

ただし、ShortTitle が次のようになっているため、問題が発生しています。

Liverpool - 1
Liverpool - 2
...
Liverpool - 9
Liverpool - 10
Liverpool - 11
West Kirby - 1
West Kirby - 8
West Kirby - 12

LINQ を使用してこれを並べ替えると、順番に表示されます

Liverpool - 1
Liverpool - 11
Liverpool - 12
Liverpool - 2
West Kirby - 1
West Kirby - 12
West Kirby - 8

ShortTitle は常に単語の文字列で、その後に 1 つのハイフンと数字が続きます。

これを正しくソートする方法はありますか?

4

5 に答える 5

20

これを試して

List<string> list = new List<string>() { 
    "Liverpool - 1",
    "Liverpool - 11",
    "Liverpool - 12",
    "Liverpool - 2",
    "West Kirby - 1",
    "West Kirby - 12",
    "West Kirby - 8" };
var sortedList = list.CustomSort().ToArray();    


public static class MyExtensions
{
    public static IEnumerable<string> CustomSort(this IEnumerable<string> list)
    {
        int maxLen = list.Select(s => s.Length).Max();

        return list.Select(s => new
        {
            OrgStr = s,
            SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, char.IsDigit(m.Value[0]) ? ' ' : '\xffff'))
        })
        .OrderBy(x => x.SortStr)
        .Select(x => x.OrgStr);
    }

}
于 2012-06-15T14:03:56.493 に答える
10

これは、文字列として並べ替えているためです。文字列の場合、11は2の前にあります。最後にShortTitle(私が想定している)int値を与えるためにを解析し、それで並べ替える必要があります。

LINQクエリをこれに変更して、機能させることができます。

var query = _cityRepository.GetAll(
           .OrderBy(item => item.RowKey.Substring(0, 4))
           .ThenBy(item => item.ShortTitle.Split('-').First())
           .ThenBy(item => Convert.ToInt16(item.ShortTitle.Split().Last()));
于 2012-06-15T14:03:12.273 に答える
3

迅速かつ汚い:

class Program
{
    static void Main(string[] args)
    {
        var list = new[] {"Liverpool - 1", 
                          "Liverpool - 11",
                          "Liverpool - 123",
                          "Liverpool - 342",
                          "Liverpool - 2"};

        foreach (var x in list.OrderBy(s => Int32.Parse(Regex.Match(s, @"- (\d*)").Groups[1].Value)))
            Console.WriteLine(x);
    }
}
于 2012-06-15T14:17:54.887 に答える
1

パーティーに遅れましたが、それで止められません!

@NominSimの素晴らしいソリューションに便乗:

var query = _cityRepository.GetAll()
           .Select(item => 
             {
               var fields = item.ShortTitle.Split('-');
               return new
               {
                 Key = item.RowKey.Substring(0,4),
                 Title = fields[0].Trim(),
                 Index = Convert.ToInt16(fields[1])
               }
             })
           .OrderBy(item => item.Key)
           .ThenBy(item => item.Title)
           .ThenBy(item => item.Index);

実際、主な違いは、分割の結果をキャプチャすることです。これにより、インデックスを取得するために分割を再度実行する必要がなくなり、タイトルにTrim()を追加しました。

于 2012-07-23T18:21:07.203 に答える
0

独自の Comparer を作成し、それを OrderBy またはThenByに渡して、必要な方法で文字列を並べ替えることができます。

たとえば、この非常に原始的な比較子は、文字列を変換する前に最後の数字を 0 で埋めます。

class MyComparer:Comparer<string>
{
    public override int Compare(string x, string y)
    {
        var xL = xparts[xparts.Length - 1];
        long xN;
        if (long.TryParse(xL,out xN))
        {
            xparts[xparts.Length - 1] = xN.ToString().PadLeft(20,'0');
        }

        var yL = yparts[yparts.Length - 1];
        long yN;
        if (long.TryParse(yL, out yN))
        {
            yparts[yparts.Length - 1] = yN.ToString().PadLeft(20, '0');
        }

        var x2=String.Join(" ", xparts);
        var y2 = String.Join(" ", yparts);

        return x2.CompareTo(y2);
    }
}

最小限の変更で呼び出すことができます。

var query = _cityRepository.GetAll(
           .OrderBy(item => item.RowKey.Substring(0, 4))
           .ThenBy(item => item.ShortTitle, new MyComparer());
于 2012-06-15T14:06:14.483 に答える