如何按C#列表排序,以便重复的项目按其插入的相反顺序显示

时间:2018-05-21 22:02:30

标签: c# .net list linq

如何按列表排序,以便重复项以插入的相反顺序出现(考虑到我不会通过使用列表的插入方法在中间插入任何项目)

采取以下示例:

public class Program
{
    public static void Main(string[] args)
    {
        List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();

        list.Add(new KeyValuePair<int, string>(1, "A"));
        list.Add(new KeyValuePair<int, string>(3, "F"));
        list.Add(new KeyValuePair<int, string>(4, "G"));
        list.Add(new KeyValuePair<int, string>(2, "B"));
        list.Add(new KeyValuePair<int, string>(2, "C"));
        list.Add(new KeyValuePair<int, string>(3, "E"));
        list.Add(new KeyValuePair<int, string>(3, "D"));

        list=list.OrderBy(a=>a.Key).ToList();

        foreach(var item in list)
        {
            Console.WriteLine(item);
        }
    }
}

输出:

[1, A]
[2, B]
[2, C]
[3, F]
[3, E]
[3, D]
[4, G]

我希望以相反的顺序插入重复的顺序,例如: G。 F,E,D应显示为D,E,F。

我虽然orderByDescending可以做到这一点,但这也会保持插入的顺序。

3 个答案:

答案 0 :(得分:4)

OrderBy是一种稳定的排序,这意味着无法区分的项目保持相同的顺序。 https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=netframework-4.7.2

这意味着重复的项目将按照添加的顺序保留,以便我们可以执行此操作

list = list
        .GroupBy(kvp => kvp.Key)
        .OrderBy(kvp => kvp.Key)
        .SelectMany(g => g.Reverse())
        .ToList();

因此我们按键分组,唯一的项目将在组中有1个项目,重复项目将包含多个项目。组中的项目与源Enumerable的顺序相同,请参阅here

因此我们可以按照组的键进行排序,并且对于每个组,我们以相反的顺序选择其项目。

这也是有效的

list = list
        .Select((x, i) => new { Item = x, Index = i })
        .OrderBy(_ => _.Item.Key)
        .ThenByDescending(_ => _.Index)
        .Select(_ => _.Item)
        .ToList();

这样可以使用Select Override为您提供集合中项目的索引以及项目

答案 1 :(得分:1)

试试这个:

libraryDependencies += "com.company" %% "del" % "10.0.12"

我相信这会给你想要的结果。但不是你解释过的逻辑执行。

为了通过插入来订购它们,您需要跟踪该信息的方式。在您当前的代码中,您的订单不了解项目何时添加到列表中,它只知道密钥和值。

您可以使用自定义对象而不是键值对来执行此操作。

组成的对象
list=list.OrderBy(a => a.Key).ThenBy(a => a.Value).ToList();

用它自己的Add()方法就行了。使用outer int作为插入顺序。使用覆盖来添加()以获取列表的当前长度并在添加新对象之前增加插入顺序,从而保持正确的顺序,无论其插入的索引如何。

答案 2 :(得分:1)

我还没有仔细检查语法,但是......

list
    .Zip(Enumerable.Range(0, list.Count), (item, insertOrder) => new { Item = item, InsertOrder = insertOrder })
    .OrderBy(x => x.Item.Key)
    .ThenBy(x => x.InsertOrder)
    .Select(x => x.Item)
    .ToList();

这样做是创建一个Enumerable.Range来记录每个项目的广告订单顺序,然后它是OrderByThenBy正确订购商品的直接案例,然后Select再次删除InsertOrder

正如user7396598非常正确指出的那样,列表的IEnumerable顺序不一定是它们的插入顺序。但是,如果您在已经插入项目的已知上下文中使用它而不使用特定索引,那么它就足够了。如果上下文未知,您需要扩展您捕获的数据以包含插入顺序,可能是通过创建自己的集合类来记录插入顺序并且不允许插入索引

希望这有帮助