【问题标题】:Sort a List and keep a particular element at end of list after sorting排序列表并在排序后将特定元素保留在列表末尾
【发布时间】:2016-07-03 16:26:52
【问题描述】:

我有一个包含"Others" 的字符串列表。我得到这个下拉列表。我按字母顺序对这个列表进行排序。但我需要"Others" 总是在列表的末尾。我不想在排序后添加这个元素,这是一种解决方案。有没有其他方法可以通过使用.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);
                    }
                }
            }
        }

并将其称为:

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

如果可能,请帮忙。

【问题讨论】:

  • 添加“如果 y 包含 'other' return 1” 也
  • 为什么不使用字典?将“其他”作为键,将排序列表作为值

标签: c# linq list sorting


【解决方案1】:

使用这个逻辑

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

输出:

a b c x y z 其他

如果你想让other 出现在列表的顶部,那就去吧

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

输出:

其他 a b c x y z

【讨论】:

  • 其实我已经试过了,但是没有用。我的列表是具有 id 和 value 的对象列表,我尝试过像 "l.OrderBy(i => i.Value != "other").ThenBy(i => i.value).ToList();"但它不适合我
  • 是根本没有排序还是other没有出现在正确的位置?
  • 我尝试使用 != 和 == 运算符,但两端均未出现“其他”。结果与正常 orderby(value) 相同
  • 这里可能有点晚了,但是: l.OrderByDescending(i=>i.Equals("other").ThenBy(i=>i).ToList() 对我有用位居榜首。
【解决方案2】:

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

测试:

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

比较器:

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

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

【讨论】:

  • 这是一个更好的解决方案,因为它避免了制作列表的临时副本(Linq 解决方案会这样做)。虽然如果列表很小,这并不重要。
【解决方案3】:

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

object.Text = "a" 对象.值 = 1

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

object.Text = "其他" object.Value = 3

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

以下对我有用:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 2017-04-05
    • 1970-01-01
    相关资源
    最近更新 更多