简体   繁体   English

Linq使用Null值排序

[英]Linq sort with Null values

I have a class with one string property and it can be null sometimes or it can be a integer number some times or it can be a string . 我有一个带有一个字符串属性的类,它有时可以为null,或者它可以是一个整数,或者它可以是一个字符串。

I want to sort on the basis of this property using LINQ with ascending order of integer values and all nono integer values next and null values in the end 我想在这个属性的基础上使用LINQ进行排序,使用整数值的升序和接下来的所有nono整数值以及最后的null值

How can I make a LINQ expression that handles the scenarios 如何创建处理场景的LINQ表达式

Example

"1" ,NULL , "34", "6" ,"67",NULL ,"r45","j34" ,"s"  to be sorted as 

"1" "6" "34"  "67" "j34" "r45" "s" NULL NULL

I tried something like this but not really perfect the answer is 我试过这样的事情,但答案并不是很完美

var licenseitems_master =  my master list 
var firstPart = licenseitems_master.Where(x => !String.IsNullOrEmpty(x.Page) && x.Page.All(char.IsDigit)).OrderBy(x => Convert.ToInt32(x.Page));
var secondPart = licenseitems_master.Where(x => !String.IsNullOrEmpty(x.Page) && !x.Page.All(char.IsDigit)).OrderBy(x => x.Page);
var thirdPart = licenseitems_master.Where(x => String.IsNullOrEmpty(x.Page)).ToList();
var sorted_items = firstPart.Union(secondPart).Union(thirdPart).ToList();

Can we make it as a single LINQ expression? 我们可以将它作为单个LINQ表达式吗?

The typical approach in such scenario is to order first by some priority expression, then the rest (which takes effect only for equal priorities) by something else. 这种情况下的典型方法是先通过某种优先级表达式进行排序,然后通过其他方式对其余部分(仅对相同的优先级生效)进行排序。 In your scenario it could be something like this: 在您的方案中,它可能是这样的:

var sorted_items =
    (from x in licenseitems_master
     let pageOrder = string.IsNullOrEmpty(x.Page) ? 2 : x.Page.All(char.IsDigit) ? 0 : 1
     orderby pageOrder, pageOrder == 0 ? Convert.ToInt32(x.Page) : 0, x.Page
     select x).ToList();

Here is one approach with Linq 这是Linq的一种方法

  • first order by ascending null / not nul 第一顺序是升序null / not nul
  • then order by ascending the numbers 然后通过提升数字来排序
  • then order by ascending 然后按升序排序

tested with List<string> 使用List<string>进行测试

var input = new List<string>() { "1", null, "34", "6", "67", null, "r45", "j34", "s" };
List<string> result = input.OrderBy(x => x == null)
      .ThenBy(x => x != null && x.All(y => char.IsDigit(y)) ? int.Parse(x) : int.MaxValue)
      .ThenBy(x => x).ToList();

I would also prefer a custom comparer for that case (which is easier to read / maintain) but the question was about a Linq approach 我也更喜欢这种情况的自定义比较器(更容易阅读/维护),但问题是关于Linq方法

You could also go for something like that. 你也可以去做那样的事情。

First : TryParse to int, and order by that value (if you can't parse, replace the value by Int32.MaxValue, which will put these values at the end). 首先:TryParse为int,并按该值排序(如果你不能解析,则用Int32.MaxValue替换值,这将把这些值放在最后)。

Second: put null at end. 第二:在结尾处输入null。

Third: Order that result by "string" value 第三:按“字符串”值排序

int outValue;
var result = input
                .OrderBy(m => Int32.TryParse(m, out outValue)
                    ? outValue
                    : Int32.MaxValue)
                .ThenBy(m => m == null)
                .ThenBy(m => m)
                .ToList();

Maybe you could use this kind of comparer: 也许你可以使用这种比较器:

public class MyComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (x == null && y == null) return 0;
        if (x == null) return 1;
        if (y == null) return -1;

        if (x.All(char.IsDigit) && y.All(char.IsDigit))
        {
            var n1 = Convert.ToInt32(x);
            var n2 = Convert.ToInt32(y);
            return n1 - n2;
        }
        return x.CompareTo(y);
    }
}

And then use it like this: 然后像这样使用它:

var myComparer = new MyComparer();
var sorted_items = "my master list".OrderBy(x => x.Page, myComparer).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM