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 => c.Key[0]
来只比较密钥的第一个字符。 (但这个字符必须是唯一的)
如果你有非唯一键,你可以按键分组
var result = a
.GroupBy(c => c.Key)
.CustomSort(g => g.Key, "B", "C", "A")
.Select(g => g.ToList());
或者,如果您想按第一个字符排序:.GroupBy(c => c.Key[0])
。
【讨论】:
嘿@Olivier!此代码是使用整个 "R", "G", "W", "U" 数组作为比较值还是字符代表订单本身?关于输入中键的唯一性,您的意思是属性的值本身应该是唯一的吗?对不起,如果这个问题看起来很奇怪;我对编程比较陌生,所以一开始高级概念对我来说可能有点挑战。 这不是一般的编程问题。所需的唯一性是因为我实现此方法的方式(它将键添加到字典中)。请参阅我添加的示例。 现在我明白了!你的第二个例子有很大帮助(我可能也需要睡个好觉......)。是的,在我的示例中,唯一性也是必需的,因此这非常适合,但我也可以在稍后的另一个问题中使用您的组关键示例。我测试了您的版本并将其调整为我的字符串数组,并且都运行良好。现在我将调整逻辑以适应我的课程和代码,并且学到了一些非常有用的东西!谢谢@Olivier! :)以上是关于C#根据多个(26 + 3)类别以特定顺序对对象列表进行排序(LINQ,if else,switch case)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
s-s-rS 根据矩阵/tablix 中的特定列类别添加百分比列