C#根据多个(26 + 3)类别以特定顺序对对象列表进行排序(LINQ,if else,switch case)[关闭]

Posted

技术标签:

【中文标题】C#根据多个(26 + 3)类别以特定顺序对对象列表进行排序(LINQ,if else,switch case)[关闭]【英文标题】:C# Sorting a list of objects, according to multiple(26+3) categories in a specific order (LINQ, if else, switch case) [closed] 【发布时间】:2021-06-28 18:06:22 【问题描述】:

我有一个对象列表,我试图根据特定的类别列表进行排序/排序。类别本身是不同的字符串数组(其中 26 个 / string[] "W", "U" ),额外的是常规条件,如名称(字符串)、类型(字符串)、成本(整数)。我应该一次性订购列表,或者就像我现在部分完成的那样,准备 26 个 if 语句/switch 案例并创建 26 个子列表,我将按名称、类型、成本单独排序,然后合并到更大的 endResult列表。

string[] "W", "U" 
...
string[] "R", "G", "W", "U" 

由于 26 个类别的顺序是固定的,我考虑使用 switch case,但我不能使用字符串数组作为 switch 表达式。写 26 个 if 语句似乎是一种相当粗略的方法(更不用说实际写它了),但在这一点上,这是我能完成这项工作的唯一方法。我也试过cr

按名称、类型(对象的字符串属性)、成本(int值)进行排序在分割排序中应该没有问题,但如果我一次性这样做,我必须将它集成到主排序功能中。

所以我想知道,有没有更好的方法来解决这个问题?我能否以某种方式进行详细的 LINQ 查询以确保遵循优先级?

提前感谢您的任何提示!

编辑:由于需要澄清,因此已关闭,因此我尝试对其进行更多详细说明。

对象有一个属性 color_identity,它是一个字符串数组。

private string[] color_identity;

在排序中,我必须检查这个字段是否与26个排序类别之一相同,例如:

               new string[] "W", "U" ,
               new string[] "W", "B" ,
               new string[] "U", "B" ,
               new string[] "U", "R" ,
...
               
               new string[] "W", "U", "B" ,
               new string[] "U", "B", "R" ,
               new string[] "B", "R", "G" ,
...

               new string[] "R", "G", "W", "U" ,
               new string[] "U", "B", "R", "G" ,
               new string[] "B", "R", "G", "W" ,
...

               new string[] "W", "U", "B", "R", "G" 

结果列表中元素的顺序应基于这些类别的顺序。 是否可以一次性过滤/排序对象列表,如果是,那么如何? 还是应该将其分解为 26 个查询?有没有办法让它更有活力而不是重复?

【问题讨论】:

【参考方案1】:

我为此做了一个扩展方法

public static IEnumerable<T> CustomSort<T, TKey>(
    this IEnumerable<T> input,
    Func<T, TKey> getKey,
    params TKey[] order)

    var valueDict = input.ToDictionary(item => getKey(item));
    for (int i = 0; i < order.Length; i++) 
        if (valueDict.TryGetValue(order[i], out T item)) 
            yield return item;
        
    

getKey 是一个 lambda,它返回您要用来对对象进行排序的键。输入中的这些键在此实现中必须是唯一的。所以,我不知道这是否对您的场景有用。我的场景是使用自定义顺序按列名对包含列信息的对象进行排序。

用法:

var order = new string[] "R", "G", "W", "U" ;
var sorted = input.CustomSort(obj => obj.Key, order);

或者,因为params 数组:

var sorted = input.CustomSort(obj => obj.Key, "R", "G", "W", "U");

例子:

class C

    public string Key  get; set; 
    public string Name  get; set; 

var a = new C[] 
    new C  Key = "A", Name = "John" ,
    new C  Key = "B", Name = "Ann" ,
    new C  Key = "C", Name = "Max" 
;
var result = a.CustomSort(c => c.Key, "B", "C", "A")
    .Select(c => c.Name);

产量:安、马克斯、约翰

这里,Key 属性必须具有唯一值,Name 属性没有。 Key 的整个值必须匹配。但当然你可以写c =&gt; c.Key[0] 来只比较密钥的第一个字符。 (但这个字符必须是唯一的)

如果你有非唯一键,你可以按键分组

var result = a
    .GroupBy(c => c.Key)
    .CustomSort(g => g.Key, "B", "C", "A")
    .Select(g => g.ToList());

或者,如果您想按第一个字符排序:.GroupBy(c =&gt; c.Key[0])

【讨论】:

嘿@Olivier!此代码是使用整个 "R", "G", "W", "U" 数组作为比较值还是字符代表订单本身?关于输入中键的唯一性,您的意思是属性的值本身应该是唯一的吗?对不起,如果这个问题看起来很奇怪;我对编程比较陌生,所以一开始高级概念对我来说可能有点挑战。 这不是一般的编程问题。所需的唯一性是因为我实现此方法的方式(它将键添加到字典中)。请参阅我添加的示例。 现在我明白了!你的第二个例子有很大帮助(我可能也需要睡个好觉......)。是的,在我的示例中,唯一性也是必需的,因此这非常适合,但我也可以在稍后的另一个问题中使用您的组关键示例。我测试了您的版本并将其调整为我的字符串数组,并且都运行良好。现在我将调整逻辑以适应我的课程和代码,并且学到了一些非常有用的东西!谢谢@Olivier! :)

以上是关于C#根据多个(26 + 3)类别以特定顺序对对象列表进行排序(LINQ,if else,switch case)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

s-s-rS 根据矩阵/tablix 中的特定列类别添加百分比列

根据 Azure 流分析中的时间顺序获取记录的最后一个值

着色Highcharts类别

Angular 2 - 如何以特定顺序在组件中实例化多个服务?

如何根据日期对SQL Server中的多个列进行排序

如何使用快速编码根据特定的排序顺序对自定义对象进行排序