C#Linq OrderBy过滤null或空值为last

时间:2012-11-28 12:02:54

标签: c# linq expression

我尝试使用自定义orderby扩展方法,我成功地处理了我的代码,但另外我想在结果中列出空值或空值或零值,任何人都可以帮我解决这个问题吗?

这是orderby的扩展方法

    public static IQueryable<T> OrderBy<T>(this IQueryable<T> q, string SortField, bool isAsc)
    {
        //var nullExpr = Expression.Constant(null, typeof(T));
        var param = Expression.Parameter(typeof(T), "p");
        var prop = Expression.Property(param, SortField);
        var exp = Expression.Lambda(prop, param);
        string method = isAsc ? "OrderBy" : "OrderByDescending";
        Type[] types = new Type[] { q.ElementType, exp.Body.Type };
        var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
        return q.Provider.CreateQuery<T>(mce);
    }

提前致谢

6 个答案:

答案 0 :(得分:35)

最简单的方法是使用

OrderBy(e => String.IsNullOrEmpty(e.TeamName)

这不需要任何扩展方法或自定义IComparer实现等。

var entries = repository.Race.Where(e => e.EventId == id)
                      .OrderBy(e => String.IsNullOrEmpty(e.TeamName))
                      .ThenBy(e => e.LastName)
                      .ThenBy(e => e.FirstName);

答案 1 :(得分:21)

不使用扩展方法......

创建自定义IComparer<string>以在使用默认String.Compare之前检查空值。如果使用标准字符串比较,则第一次检查将返回-1而不是1或1而不是-1。

/// <summary>
/// Returns -1 instead of 1 if y is IsNullOrEmpty when x is Not.
/// </summary>
public class EmptyStringsAreLast : IComparer<string>
{
    public int Compare(string x, string y)
        {
            if (String.IsNullOrEmpty(y) && !String.IsNullOrEmpty(x))
            {
                return -1;
            }
            else if (!String.IsNullOrEmpty(y) && String.IsNullOrEmpty(x))
            {
                return 1;
            }
            else
            {
                return String.Compare(x, y);
            }
        }
 }

将您的EmptyStringsAreLast比较器传递到Lambda表达式的OrderBy。在此解决方案中,参加比赛的团队应按字母顺序排列,但非关联的参赛作品应在最后出现。

var entries = repository.Race.Where(e => e.EventId == id)
                          .OrderBy(e => e.TeamName, new EmptyStringsAreLast())
                          .ThenBy(e => e.LastName)
                          .ThenBy(e => e.FirstName);

答案 2 :(得分:2)

这个答案可能就是你最初想要的 - 使用你的通用扩展方法:

Release

答案 3 :(得分:0)

Dave Anson's回答的基础上,您可以使用Comparer.Create()从lambda创建Comparer。以下是unsorted字符串字段排序myString的示例,其中null或空字符串最后出现。

var sorted = unsorted.OrderBy(x => x.myString, Comparer<string>.Create((x, y) => { 
             if ( string.IsNullOrEmpty(y) && !string.IsNullOrEmpty(x)) return -1;
        else if (!string.IsNullOrEmpty(y) &&  string.IsNullOrEmpty(x)) return +1;
        else return string.Compare(x, y);
    }))

(首先将它们放在1常数上)

答案 4 :(得分:0)

它对我有用:

    private static IQueryable<T> GetOrderQuery<T>(this IQueryable<T> q, BaseFilterCollection filter)
    {
        q = q.OrderBy(GetExpression<T>(filter.SortField));

        var param = Expression.Parameter(typeof(T), "p");
        var prop = Expression.Property(param, filter.SortField);
        var exp = Expression.Lambda(prop, param);
        string method = filter.SortDirection == SortDirectionType.Asc ? "ThenBy" : "ThenByDescending";
        Type[] types = { q.ElementType, exp.Body.Type };
        var rs = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
        return q.Provider.CreateQuery<T>(rs);
    }

    private static Expression<Func<T, bool>> GetExpression<T>(string sortField)
    {
        ParameterExpression param = Expression.Parameter(typeof(T), "p");
        Expression prop = Expression.Property(param, sortField);

        var info = typeof(T).GetProperty(sortField, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
        Expression exp = Expression.Equal(prop, info.PropertyType.IsValueType 
            ? Expression.Constant(Activator.CreateInstance(info.PropertyType)) 
            : Expression.Constant(null));

        return Expression.Lambda<Func<T, bool>>(exp, param);
    }

答案 5 :(得分:0)

你不需要复杂化,最简单的方法是做这样的事情:

YourList.OrderByDescending(x => string.IsNullOrEmpty(x.value)

使用 OrderByDescending 或 OrderBy,具体取决于您想在开头还是最后看到空字符串。

问候