C#如何根据动态键名列表按内嵌键值对对对象集合排序
动态多条件排序实现方案
完全可以实现按传入的字符串键名列表、严格遵循优先级顺序对内嵌键值对集合的对象列表排序,核心实现逻辑如下:
第一步:定义对应数据结构
首先根据你的JSON结构定义C#实体类:
/// <summary> /// 产品实体 /// </summary> public class Product { public string uid { get; set; } public string gamme { get; set; } public string serie { get; set; } public string description { get; set; } public List<Caracteristique> caracteristiques { get; set; } } /// <summary> /// 内嵌属性键值对实体 /// </summary> public class Caracteristique { public string name { get; set; } public string value { get; set; } }
第二步:实现动态排序扩展方法
封装通用的排序扩展方法,支持传入任意顺序的条件键名列表:
public static class ProductSortExtension { public static IEnumerable<Product> OrderByDynamicConditions( this IEnumerable<Product> source, IList<string> sortKeyPriority, bool conditionFirst = false, bool isAscending = true) { if (source == null) throw new ArgumentNullException(nameof(source)); if (sortKeyPriority == null || sortKeyPriority.Count == 0) throw new ArgumentException("排序键列表不可为空"); // 预生成每个产品的条件键值索引,避免排序时重复遍历数组查找 var productMap = source.Select(p => new { Origin = p, ConditionMap = p.caracteristiques .ToDictionary(c => c.name, c => c.value) }).ToList(); // 构建排序逻辑 IOrderedEnumerable<dynamic> sortedQuery; Func<dynamic, object> firstKeySelector = item => item.ConditionMap.TryGetValue(sortKeyPriority[0], out var v) ? v : string.Empty; sortedQuery = isAscending ? productMap.OrderBy(firstKeySelector) : productMap.OrderByDescending(firstKeySelector); for (var i = 1; i < sortKeyPriority.Count; i++) { var key = sortKeyPriority[i]; Func<dynamic, object> keySelector = item => item.ConditionMap.TryGetValue(key, out var v) ? v : string.Empty; sortedQuery = isAscending ? sortedQuery.ThenBy(keySelector) : sortedQuery.ThenByDescending(keySelector); } // 拼接固定字段排序,根据conditionFirst参数决定优先级 var result = sortedQuery.Select(i => i.Origin); result = conditionFirst ? result.ThenBy(x => x.gamme).ThenBy(x => x.serie) : result.OrderBy(x => x.gamme).ThenBy(x => x.serie); return result; } }
第三步:调用示例
直接传入你需要的排序优先级列表即可完成排序:
// 定义动态排序键优先级 var sortPriority = new List<string> {"Condition1", "Condition2", "Condition3", "Condition4"}; // 调用排序方法:如果动态条件优先级高于gamme/serie,把第二个参数设为true即可 var sortedList = Lprod.OrderByDynamicConditions(sortPriority, conditionFirst: false).ToList();
注意事项
- 上述实现默认按字符串规则排序,如果存在数值类条件(比如示例中的Condition1、Condition3为数字),可以在键值取值逻辑中增加类型判断,可转为数值的字段按数值类型排序,避免字符串排序导致的顺序异常(比如字符串规则下
"9.8" < "80"不成立)。 - 若产品对象缺少传入的排序键,代码默认返回空字符串作为排序值,你可以根据业务需求调整缺失键的默认值。
- 如果需要支持不同排序键对应不同升降序规则,只需要把传入的字符串列表替换为
(键名, 是否升序)的元组列表,微调排序逻辑即可。
排序优先级可灵活调整:如果你需要把gamme、serie作为最高优先级排序条件,保持默认参数即可;如果动态传入的条件优先级更高,传入
conditionFirst: true即可。
内容的提问来源于stack exchange,提问作者Taieb
相关产品推荐
相关产品推荐

