Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有空值的Linq排序_C#_Linq_Linq To Sql - Fatal编程技术网

C# 具有空值的Linq排序

C# 具有空值的Linq排序,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,我有一个具有一个字符串属性的类,它有时可以为null,有时可以是整数,有时也可以是字符串 我想在这个属性的基础上使用LINQ对整数值进行升序排序,然后是所有非O整数值,最后是null值 如何生成处理场景的LINQ表达式 范例 "1" ,NULL , "34", "6" ,"67",NULL ,"r45","j34" ,"s" to be sorted as "1" "6" "34" "67" "j34" "r45" "s" NULL NULL 我试过这样的方法,但并不完美答案是 var

我有一个具有一个字符串属性的类,它有时可以为null,有时可以是整数,有时也可以是字符串

我想在这个属性的基础上使用LINQ对整数值进行升序排序,然后是所有非O整数值,最后是null值

如何生成处理场景的LINQ表达式

范例

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

"1" "6" "34"  "67" "j34" "r45" "s" NULL NULL
我试过这样的方法,但并不完美答案是

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();

我们可以将其作为单个LINQ表达式吗?

这里有一种使用LINQ的方法

  • 按升序null/not nul排列的一阶
  • 然后按升序排列
  • 然后按升序排列
使用
列表测试

var input=newlist(){“1”,null,“34”,“6”,“67”,null,“r45”,“j34”,“s”};
列表结果=输入.OrderBy(x=>x==null)
.ThenBy(x=>x!=null&&x.All(y=>char.IsDigit(y))?int.Parse(x):int.MaxValue)
.ThenBy(x=>x).ToList();

我也更喜欢这种情况下的自定义比较器(更易于阅读/维护),但问题是关于
Linq
方法的问题,在这种情况下,典型的方法是先按某个优先级表达式排序,然后按其他方式排序(仅对相同优先级有效)。在您的场景中,可能是这样的:

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();
var myComparer = new MyComparer();
var sorted_items = "my master list".OrderBy(x => x.Page, myComparer).ToList();

也许你可以使用这种比较器:

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);
    }
}

你也可以做类似的事情

首先:将TryParse转换为int,并按该值排序(如果无法解析,请将该值替换为Int32.MaxValue,这将把这些值放在末尾)

第二:将null放在末尾

第三:按“字符串”值对结果排序


你应该使用你自己的比较器。很好的解释是,您必须重写类中的
Equals
GetHashCode
方法。然后就可以像
var-sorted\u items=licenseitems\u master.OrderBy(x=>x.Page.ToList()一样简单了为什么在一个变量中有不同的数据类型?这是客户机的要求。页面可以是字符串,有时类似于示例rj45,或者只是一个数字,而不是强制的field@PawełHemperek:嗯,不太可能。只需将使用
Union
更改为
Concat
即可避免使用任何相等比较。自定义比较器是执行排序的正确方法。这正是我要寻找的。我试过了,但顺序不是真的升序,我得到的结果是1,34,6,67,j34,r45,null,null。但是它应该是1,6,34,67,j34,r45,null,null@JibinMathew修正了
var myComparer = new MyComparer();
var sorted_items = "my master list".OrderBy(x => x.Page, myComparer).ToList();
int outValue;
var result = input
                .OrderBy(m => Int32.TryParse(m, out outValue)
                    ? outValue
                    : Int32.MaxValue)
                .ThenBy(m => m == null)
                .ThenBy(m => m)
                .ToList();