C# LINQ多条件排序:按gamme、serie及嵌套特性指定顺序排序
LINQ 动态多级嵌套属性排序实现方案
核心实现逻辑
- 前两级
gamme、serie排序逻辑保持原有写法即可 - 第三级动态排序通过遍历预先配置的特性优先级列表,循环向已排序的查询追加
ThenBy条件实现,配置变更时无需修改核心排序代码 - 针对尺寸类数值型特性值做类型兼容处理,避免字符串排序导致的数值顺序错误(如字符串比较下
"100" < "9"的逻辑问题) - 增加空值容错:缺失对应特性、特性值为空的产品统一排到同分组末尾,避免空引用异常
完整可运行代码
using System.Globalization; // 可动态调整的第三级排序特性优先级,顺序越靠前优先级越高,业务变更时直接修改该列表即可 var featureSortPriority = new List<string> { "largeur", "longueur", "epaisseur", "type_pose" }; // 初始化前两级固定排序 IOrderedEnumerable<Product> sortedProducts = listOfProducts .OrderBy(p => p.gamme) .ThenBy(p => p.serie); // 循环追加动态配置的排序规则 foreach (var featureName in featureSortPriority) { // 捕获当前循环变量,避免闭包取值异常 string currentFeature = featureName; sortedProducts = sortedProducts.ThenBy(p => { Caracteristique? target = p.caracteristiques? .FirstOrDefault(c => c.nom.Equals(currentFeature, StringComparison.OrdinalIgnoreCase)); // 标记是否存在有效值,缺失的项统一排到最后 if (target == null || string.IsNullOrWhiteSpace(target.valeur)) return (HasValue: 1, SortValue: null as object); // 尝试转数值做数值排序,转换失败按字符串排序 if (decimal.TryParse(target.valeur, NumberStyles.Float, CultureInfo.InvariantCulture, out decimal numVal)) return (HasValue: 0, SortValue: (object)numVal); return (HasValue: 0, SortValue: (object)target.valeur); }, Comparer<(int HasValue, object SortValue)>.Create((a, b) => { // 先比较是否存在有效值,缺失值排后 int flagCompare = a.HasValue.CompareTo(b.HasValue); if (flagCompare != 0) return flagCompare; if (a.SortValue == null && b.SortValue == null) return 0; // 数值类型按数值比较,否则按字符串比较 if (a.SortValue is decimal aNum && b.SortValue is decimal bNum) return aNum.CompareTo(bNum); return string.Compare(a.SortValue?.ToString(), b.SortValue?.ToString(), StringComparison.OrdinalIgnoreCase); })); } // 最终排序结果 List<Product> result = sortedProducts.ToList();
注意事项
该实现为内存集合排序逻辑,如果是基于EF Core等ORM的数据库查询场景,需要先调用
.AsEnumerable()或.ToList()将数据加载到内存后再执行上述动态排序,避免ORM无法翻译动态排序表达式抛出异常。
对应结构类定义(和给出的JSON结构完全匹配)
public class Product { public string uid { get; set; } public string gamme { get; set; } public string serie { get; set; } public List<Caracteristique> caracteristiques { get; set; } } public class Caracteristique { public string nom { get; set; } public string label { get; set; } public string valeur { get; set; } }
内容的提问来源于stack exchange,提问作者Taieb
相关产品推荐
相关产品推荐

