ASP.Net EF Order不是自然排序

时间:2017-05-15 08:29:52

标签: c# asp.net asp.net-mvc entity-framework

我正在写搜索功能。我的Db字段为字符串(Nvarchar(MAX)),此字段包含字符串和数字

DB DATAS    EF ORDER          I want to
a 1          a 1                a 1
a 20         a 12               a 2
a 2          a 2                a 12
a 12         a 20               a 20
a 25         a 25               a 25
b 1          b 1                b 1
b 5          b 5                b 5
....         ...                ....

3 个答案:

答案 0 :(得分:0)

您需要实现IComparer接口并创建NaturalStringComparer以便以您希望的方式比较字符串。请参阅下面的代码。

public class NaturalStringComparer : IComparer<string>
{
    private static readonly Regex _re = new Regex(@"(?<=\D)(?=\d)|(?<=\d)(?=\D)", RegexOptions.Compiled);

    public int Compare(string x, string y)
    {
        x = x.ToLower();
        y = y.ToLower();
        if (string.Compare(x, 0, y, 0, Math.Min(x.Length, y.Length)) == 0)
        {
            if (x.Length == y.Length) return 0;
            return x.Length < y.Length ? -1 : 1;
        }
        var a = _re.Split(x);
        var b = _re.Split(y);
        int i = 0;
        while (true)
        {
            int r = PartCompare(a[i], b[i]);
            if (r != 0) return r;
            ++i;
        }
    }

    private static int PartCompare(string x, string y)
    {
        int a, b;
        if (int.TryParse(x, out a) && int.TryParse(y, out b))
            return a.CompareTo(b);
        return x.CompareTo(y);
    }
}

对字符串和整数的混合进行排序的示例:

var x = new List<string>() { "a 1", "a 20", "a 2", "a 12" };
var y = x.OrderBy(m => m, new NaturalStringComparer()).ToList();
  

输入:“a 1”,“a 20”,“a 2”,“a 12”

     

输出:“a 1”,“a 2”,“a 12”,“a 20”

答案 1 :(得分:0)

您可以执行以下操作:

    var lists = strs.Select(str => new Regex(@"([a-zA-Z]+)(\d+)").Match(Regex.Replace(str, @"\s+", "")))
        .Select(result => new
        {
            str = result.Groups[1].Value,
            num = result.Groups[2].Value
        })
        .ToList().OrderBy(s=>s.str).ThenBy(s=>s.num).Select(s=> new {result=s.str+" "+s.num}).ToList();

答案 2 :(得分:0)

在你的情况下(一封带有数字的字母),你可能需要这样的数字填充(归功于Nathan):

public static string PadNumbers(string input)
{
    // replace number "2" into number of digits you want to group with
    return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(2, '0'));
}

这种方式在OrderBy子句中的数字部分启用填充,应该像这样使用:

var naturalOrder = list.OrderBy(x => PadNumbers(x));

通过使用上面的填充正则表达式,OrderBy将看到如下数字部分:

a 01
a 20
a 02
a 12
a 25
...

然后按照这样排序:

a 01
a 02
a 12
a 20
a 25
...

当然,填充仅在决定数字顺序时用于比较,原始字符串仍然保留。

填充使用背后的原因是按字典顺序使用OrderBy的默认排序,它从左到右处理字符串中的字符。

工作示例:NET Fiddle Demo

类似问题:

Alphanumeric sorting using LINQ