排序列表并在排序后将特定元素保留在列表的末尾

时间:2021-03-27 17:12:55

I have a list of string containing "Others". I am getting this list for drop down. I am sorting this list alphabetically. But I need "Others" always at end of list. I don't want to add this element after sorting which is one solution. Is there any other way to do the same like by using custom comparer of .Sort() method. I tried like below but no solution.

我有一个包含“其他”的字符串列表。我得到这个列表下拉。我按字母顺序排序这个列表。但我需要“其他人”总是在列表的末尾。我不想在排序后添加这个元素,这是一个解决方案。有没有其他方法可以像使用.Sort()方法的自定义比较器一样。我试过下面但没有解决方案。

 public class EOComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    if (x.ToLower().Contains("other"))
                    {
                        return -1;
                    }
                    else
                    {
                        // If the strings are of equal length,
                        // sort them with ordinary string comparison.
                        //
                        return x.CompareTo(y);
                    }
                }
            }
        }

and calling it as :

并将其称为:

EOComparer c = new EOComparer();
a.Sort((x, y) => c.Compare(x.OptionValue, y.OptionValue));
             return a;

Please help if it is possible.

如果有可能请帮忙。

3 个解决方案

#1


10  

This is a fine answer, but I thought I would fix your comparer:

这是一个很好的答案,但我想我会修复你的比较器:

Test:

测试:

[TestCase(new string[0], new string[0])]
[TestCase(new[] { "a" }, new[] { "a" })]
[TestCase(new[] { "a", "b" }, new[] { "a", "b" })]
[TestCase(new[] { "b", "a" }, new[] { "a", "b" })]
[TestCase(new[] {"others"}, new[] {"others"})]
[TestCase(new[] {"a", "others"}, new[] {"a", "others"})]
[TestCase(new[] {"others", "a"}, new[] {"a", "others"})]
[TestCase(new[] {"others", "x"}, new[] {"x", "others"})]
[TestCase(new[] {"Others", "x"}, new[] {"x", "Others"})]
[TestCase(new[] { "othersz", "others" }, new[] { "othersz", "others" })]
[TestCase(new[] {"z", "y", "x", "others", "b", "a", "c"},
          new[] {"a", "b", "c", "x", "y", "z", "others"})]
public void CanSortWithOthersAtEnd(string[] input, string[] expectedSorted)
{
    var a = new List<string>(input);
    var c = new EOComparer();
    a.Sort(c.Compare);
    CollectionAssert.AreEqual(expectedSorted, a);
}

Comparer:

比较器:

public sealed class EOComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (IsOthers(x)) return 1;
        if (IsOthers(y)) return -1;
        return string.Compare(x, y, StringComparison.Ordinal);
    }

    private static bool IsOthers(string str)
    {
        return string.Compare(str, "others", StringComparison.OrdinalIgnoreCase) == 0;
    }
}

Note how my use of string.Compare avoids all == null checks. And how StringComparison.OrdinalIgnoreCase avoids .ToLower() and thus avoids creating copies of the strings.

请注意我对string.Compare的使用如何避免所有== null检查。以及StringComparison.OrdinalIgnoreCase如何避免.ToLower(),从而避免创建字符串的副本。

#2


15  

Use this logic

使用这个逻辑

List<string> l = new List<string>{ "z", "y", "x", "other", "b", "a", "c" };
var result = l.OrderBy(i => i == "other").ThenBy(i => i).ToList();
result.ForEach(Console.WriteLine);

Output:

输出:

a b c x y z other

a b c x y z other

If you want other to be on top of the list make it

如果你想让其他人在列表的顶部做出来

var result = l.OrderBy(i => i != "other").ThenBy(i => i).ToList();

Output:

输出:

other a b c x y z

其他a b c x y z

#3


0  

Suppose we have objects with the following list items.

假设我们有包含以下列表项的对象。

object.Text = "a" object.Value = 1

object.Text =“a”object.Value = 1

object.Text = "b" object.Value = 2

object.Text =“b”object.Value = 2

object.Text = "other" object.Value = 3

object.Text =“other”object.Value = 3

object.Text = "c" object.Value = 4

object.Text =“c”object.Value = 4

the following works for me:

以下对我有用:

var oList = objects.OrderBy(i => i.Text != "other").ThenBy(i => i.Text);

var oList = objects.OrderBy(i => i.Text!=“other”)。ThenBy(i => i.Text);

#1


10  

This is a fine answer, but I thought I would fix your comparer:

这是一个很好的答案,但我想我会修复你的比较器:

Test:

测试:

[TestCase(new string[0], new string[0])]
[TestCase(new[] { "a" }, new[] { "a" })]
[TestCase(new[] { "a", "b" }, new[] { "a", "b" })]
[TestCase(new[] { "b", "a" }, new[] { "a", "b" })]
[TestCase(new[] {"others"}, new[] {"others"})]
[TestCase(new[] {"a", "others"}, new[] {"a", "others"})]
[TestCase(new[] {"others", "a"}, new[] {"a", "others"})]
[TestCase(new[] {"others", "x"}, new[] {"x", "others"})]
[TestCase(new[] {"Others", "x"}, new[] {"x", "Others"})]
[TestCase(new[] { "othersz", "others" }, new[] { "othersz", "others" })]
[TestCase(new[] {"z", "y", "x", "others", "b", "a", "c"},
          new[] {"a", "b", "c", "x", "y", "z", "others"})]
public void CanSortWithOthersAtEnd(string[] input, string[] expectedSorted)
{
    var a = new List<string>(input);
    var c = new EOComparer();
    a.Sort(c.Compare);
    CollectionAssert.AreEqual(expectedSorted, a);
}

Comparer:

比较器:

public sealed class EOComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (IsOthers(x)) return 1;
        if (IsOthers(y)) return -1;
        return string.Compare(x, y, StringComparison.Ordinal);
    }

    private static bool IsOthers(string str)
    {
        return string.Compare(str, "others", StringComparison.OrdinalIgnoreCase) == 0;
    }
}

Note how my use of string.Compare avoids all == null checks. And how StringComparison.OrdinalIgnoreCase avoids .ToLower() and thus avoids creating copies of the strings.

请注意我对string.Compare的使用如何避免所有== null检查。以及StringComparison.OrdinalIgnoreCase如何避免.ToLower(),从而避免创建字符串的副本。

#2


15  

Use this logic

使用这个逻辑

List<string> l = new List<string>{ "z", "y", "x", "other", "b", "a", "c" };
var result = l.OrderBy(i => i == "other").ThenBy(i => i).ToList();
result.ForEach(Console.WriteLine);

Output:

输出:

a b c x y z other

a b c x y z other

If you want other to be on top of the list make it

如果你想让其他人在列表的顶部做出来

var result = l.OrderBy(i => i != "other").ThenBy(i => i).ToList();

Output:

输出:

other a b c x y z

其他a b c x y z

#3


0  

Suppose we have objects with the following list items.

假设我们有包含以下列表项的对象。

object.Text = "a" object.Value = 1

object.Text =“a”object.Value = 1

object.Text = "b" object.Value = 2

object.Text =“b”object.Value = 2

object.Text = "other" object.Value = 3

object.Text =“other”object.Value = 3

object.Text = "c" object.Value = 4

object.Text =“c”object.Value = 4

the following works for me:

以下对我有用:

var oList = objects.OrderBy(i => i.Text != "other").ThenBy(i => i.Text);

var oList = objects.OrderBy(i => i.Text!=“other”)。ThenBy(i => i.Text);