排序列表,除了一个带有 LINQ 的条目,排在最后

Posted

技术标签:

【中文标题】排序列表,除了一个带有 LINQ 的条目,排在最后【英文标题】:Sort List except one entry with LINQ, to be at the last 【发布时间】: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 决定标准是“最后一个”值,按值。 这意味着“最后一个”单词将始终存在于列表中,您只想添加最后一个已排序的字符串。对吗?? 【参考方案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 @rawanmansour docs.microsoft.com/en-us/dotnet/api/… 表示您使用的是旧版本。你需要升级。追加就在那里。

以上是关于排序列表,除了一个带有 LINQ 的条目,排在最后的主要内容,如果未能解决你的问题,请参考以下文章

Java,特殊排序一个 ArrayList,最后有更长的条目

LINQ 将列的总和添加到列表条目

如何使用 linq 实体仅从 sql 表中选择最后一个条目

SQL Server 排序的时候使 null 值排在最后

SQL Server 排序的时候使 null 值排在最后

MySQL 将某个字段值排在最后,其余记录单独排序