【问题标题】:Sort List except one entry with LINQ, to be at the last排序列表,除了一个带有 LINQ 的条目,排在最后
【发布时间】:2021-09-20 21:39:49
【问题描述】:

我想订购一个字符串列表,但列表中的一个字符串应始终位于最后且未排序。使用 LINQ 最简单的方法是什么?

//should be ordered in:  a,b,u,z, last:
List<string> l = {"z","u","last","b","a"}; 

LINQ 中没有 append 方法之类的,是吗?

【问题讨论】:

  • “列表中的一个字符串应始终位于最后且未排序”是什么意思。请分享更多示例。
  • @AmitVerma 这个例子://应该在:a,b,u,z, last: List l = {"z","u","last"," b","a"};
  • 但是你将如何决定最后应该是哪个字符串?必须有一些决定标准。
  • @AmitVerma 决定标准是“最后一个”值,按值。
  • 这意味着“最后一个”单词将始终存在于列表中,您只想添加最后一个已排序的字符串。对吗??

标签: c# linq sorting


【解决方案1】:

更新

刚刚意识到 OP 意味着值“last”而不是 Last 元素。在这种情况下,使用

会容易得多
var result = l.OrderBy(x => string.Equals(x,"last")).ThenBy(x => x);

请注意,上面需要排序两次。您还可以定义一个 自定义比较器OrderBy 一起使用,然后跳过多个 OrderBy

public class LastSkipComparer<T> : IComparer<T> where T : IComparable<T>
{
    private Func<T,bool> _selector;
    public LastSkipComparer(Func<T,bool> selector)
    {
        _selector = selector;
    }

    public int Compare(T instanceA, T instanceB)
    {
        if(_selector(instanceA)) return 1;
        if(_selector(instanceB)) return -1;
        return instanceA.CompareTo(instanceB);
    }
}

现在你可以排序为,

var result = l.OrderBy(x=> x,
               new LastSkipComparer<string>((val)=> string.Equals(val,"last")));

样本输出

初步回答

要对除最后一个元素之外的每个元素进行排序,您可以使用SkipLast,然后对剩余的元素进行排序,然后再次追加最后一个元素。例如,

List<string> l = new[] {"z","u","last","b","a"}.ToList();
var result = l.SkipLast(1).OrderBy(x=>x).Append(l.Last());

SkipLast : 返回一个新的可枚举集合,其中包含来自源的元素,省略了源集合的最后计数元素。

Enumerable.Append : 将一个值附加到序列的末尾。

请注意SkipLast 需要 .NET(5.0, 6.0 Preview 3) 或 .NET Core(2.0, 2.1, 2.2, 3.0, 3.1) 或 .NET Standard 2.1

样本输出

【讨论】:

    【解决方案2】:

    您可以使用.Concat() 将您想要的字符串添加到末尾,也可以使用.OrderBy() 将您的字符串放在末尾,同时将所有其他字符串放在前面,然后使用.ThenBy() 对项目进行排序。 .ThenBy() 将适用于您之前的订购提供的物品组被认为是相同的。

    var list = new List<string> { "z", "u", "last", "b", "a" };
    var result = list
        .OrderBy(item => item == "last" ? 1 : 0)
        .ThenBy(item => item);
    

    或就地排序

    var list = new List<string> { "z", "u", "last", "b", "a" };
    list.Sort((left, right) => left == "last" ? 1 : right == "last" ? -1 : string.Compare(left, right));
    

    使用.Concat()

    var list = new List<string> { "z", "u", "last", "b", "a" };
    var result = list
        .Where(item => item != "last")
        .OrderBy(item => item)
        .Concat(Enumerable.Repeat("last", 1));
    

    【讨论】:

    • 你能举个例子吗?
    • @rawanmansour 是的,我已经更新了答案
    • 你正在排序 2 次。
    • @AmitVerma 不,.ThenBy() 标准不会进行第二次排序,它会扩展 .OrderBy() 以用于被认为相等的项目。
    • @Andrei15193 我不是说再去同一个列表。我的意思和你说的一样。在这个问题中,不需要后续排序。
    【解决方案3】:

    试试这个

    List<string> l = new List<string>{ "z", "u", "last", "b", "a" };
    
    var k = l.Where(x=>x!="last").OrderBy(x=>x).Append("last");
    

    【讨论】:

    • 没有.Append(),你可以用.Concat(),比如l.Where(x=&gt;x!="last").ToList().OrderBy(x=&gt;x).Concat(Enumerable.Repeat("last", 1))或者l.Where(x=&gt;x!="last").ToList().OrderBy(x=&gt;x).Concat(new []{ "last" })
    • 检查 linq,有追加。这是工作代码。
    • @AmitVerma 抱歉,但没有 .append
    • 表示您使用的是旧版本。你需要升级。追加就在那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    相关资源
    最近更新 更多