按字符串属性排序对象,最后空字符串

时间:2018-10-18 07:39:23

标签: c# asp.net .net asp.net-core asp.net-core-mvc

我有一个对象数组,所有对象都包含字符串属性。我想按字符串属性按字母顺序对对象进行排序,以使具有空字符串属性的对象位于列表的末尾。目前我有这个:

switches = switches.OrderBy(n => n.GetCurrentUser()).ToArray();

问题在于它将空字符串放在列表的顶部。如何将带有值(按字母顺序排列)的字符串的对象放在顶部,而将空字符串的对象放在底部的对象?

3 个答案:

答案 0 :(得分:2)

您可以使用:

switches = switches
    .Select(n => new { TheObject = n, User = n.GetCurrentUser() })
    .OrderBy(x => String.IsNullOrEmpty(x.User) ? 1 : 0)
    .ThenBy(x => x.User)
    .Select(x => x.TheObject)
    .ToArray();

这将首先建立两个组,一个组具有空用户,另一个组。 OrderBy会将它们移到末尾,因为1大于0。如果希望它们位于顶部,请使用OrderByDescending

然后我使用ThenBy按字母顺序排序,这仅对非空用户有效。

答案 1 :(得分:1)

OrderBy具有accepts an IComparer<>T的重载。这使您可以定义自己的排序规则。您可以从通用Comparer类开始,并覆盖Compare方法,例如:

public class EmptyLastComparer: Comparer<string>
{
    public override int Compare(string x, string y)
    {
        if (String.IsNullOrWhiteSpace(x) && !String.IsNullOrWhiteSpace(y))
        {
            return 1;
        }
        else if (String.IsNullOrWhiteSpace(x) && String.IsNullOrWhiteSpace(y))
        {
            return 0;
        }
        else if (!String.IsNullOrWhiteSpace(x) && String.IsNullOrWhiteSpace(y))
        {
            return -1;
        }
        else
        {
            return x.CompareTo(y);
        }
    }
}

要使用它,请创建一个新的EmptyLastComparer()实例并将其传递给OrderBy

var myStrings = new[] { "c", "A","a", "A","b", " ","   ",null };
var ordered=myStrings.OrderBy(x => x, new EmptyLastComparer());

字符串比较比仅比较两个字符串更为复杂。 String.Compare有重载,允许使用不区分大小写的比较,使用特定区域性等。自定义比较器可以在其构造函数中接受StringComparison参数,以允许类似内容,例如:

public class EmptyLastComparer : Comparer<string>
{
    private readonly StringComparison _comparison;

    public EmptyLastComparer(StringComparison comparison=StringComparison.CurrentCulture)
    {
        _comparison = comparison;
    }
    public override int Compare(string x, string y)
    {
        if (String.IsNullOrWhiteSpace(x) && !String.IsNullOrWhiteSpace(y))
        {
            return 1;
        }
        else if (String.IsNullOrWhiteSpace(x) && String.IsNullOrWhiteSpace(y))
        {
            return 0;
        }
        else if (!String.IsNullOrWhiteSpace(x) && String.IsNullOrWhiteSpace(y))
        {
            return -1;
        }
        else
        {
            return String.Compare(x,y, _comparison);
        }
    }
}

也许甚至像StringComparer一样添加一些预定义的比较器:

    public static EmptyLastComparer CurrentCulture =>
            new EmptyLastComparer();
    public static EmptyLastComparer CurrentCultureIgnoreCase => 
            new EmptyLastComparer(StringComparison.CurrentCultureIgnoreCase);

    public static EmptyLastComparer InvariantCulture =>
            new EmptyLastComparer(StringComparison.InvariantCulture);
    public static EmptyLastComparer InvariantCultureIgnoreCase =>
            new EmptyLastComparer(StringComparison.InvariantCultureIgnoreCase);

    public static EmptyLastComparer Ordinal =>
            new EmptyLastComparer(StringComparison.Ordinal);
    public static EmptyLastComparer OrdinalIgnoreCase =>
            new EmptyLastComparer(StringComparison.OrdinalIgnoreCase);

并以相同的方式使用它们,而不必每次都分配一个新的比较器:

var ordered=myStrings.OrderBy(x => x, EmptyLastComparer.InvariantCultureIgnoreCase);

答案 2 :(得分:1)

您还可以使用内联比较器创建:

switches.OrderBy(n => n.GetCurrentUser(),                
                Comparer<string>.Create((a, b) =>
                string.IsNullOrEmpty(a) && !string.IsNullOrEmpty(b)? 1 
                : !string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b) ? -1 
                : string.Compare(a, b)));