如何在C#中基于值将对象数组合并为单个对象?
C# 高效合并SecuritySettings的实现方案
核心需求
输入为SecurityResponse类型数组,每个元素包含colorSettings、speedSettings等多组设置集合;每组集合的项包含唯一settingKey和权限值securitySettingValue(W=写入、R=读取、H=隐藏)。需按W > R > H的宽松优先级合并相同settingKey的项,取最宽松权限,同时避免多层嵌套循环。
实现思路:利用LINQ内置方法简化逻辑
LINQ的SelectMany、GroupBy、Max等内置方法可以完全替代手动嵌套循环,且内部经过性能优化,代码更简洁易维护。
第一步:定义基础类型(明确结构)
先把相关类型定义清楚(如果已有类型,可跳过此步):
// 用枚举表示权限,按严格到宽松排序,枚举值越大权限越高 public enum SecurityPermission { H, R, W } public class SecuritySetting { public string SettingKey { get; set; } public SecurityPermission SecuritySettingValue { get; set; } } public class SecurityResponse { public IEnumerable<SecuritySetting> ColorSettings { get; set; } public IEnumerable<SecuritySetting> SpeedSettings { get; set; } // 其他设置集合(如SoundSettings等)可按需添加 }
第二步:全局合并所有设置(返回字典)
如果需要将所有类型的设置合并为一个按settingKey索引的字典,可直接用以下实现:
public Dictionary<string, SecurityPermission> MergeAllSecuritySettings(SecurityResponse[] responses) { // 定义所有需要提取的设置集合 var settingExtractors = new Func<SecurityResponse, IEnumerable<SecuritySetting>>[] { response => response.ColorSettings, response => response.SpeedSettings // 追加其他设置集合的提取逻辑... }; return responses // 扁平化所有设置集合,避免嵌套循环 .SelectMany(response => settingExtractors.SelectMany(extractor => extractor(response))) // 按settingKey分组 .GroupBy(setting => setting.SettingKey) // 每组取权限最高的项,转为字典 .ToDictionary( group => group.Key, group => group.Max(setting => setting.SecuritySettingValue) ); }
第三步:按原设置类型分组合并
如果需要保留原有的ColorSettings、SpeedSettings分组结构,可拆分出通用的单类型合并方法:
// 合并后的结果类型,与SecurityResponse结构一致 public class MergedSecuritySettings { public IEnumerable<SecuritySetting> ColorSettings { get; set; } public IEnumerable<SecuritySetting> SpeedSettings { get; set; } // 对应原类型的其他设置集合... } public MergedSecuritySettings MergeSecuritySettingsByType(SecurityResponse[] responses) { return new MergedSecuritySettings { ColorSettings = MergeSingleSettingGroup(responses, r => r.ColorSettings), SpeedSettings = MergeSingleSettingGroup(responses, r => r.SpeedSettings) // 其他设置类型的合并调用... }; } // 通用的单类型设置合并方法 private IEnumerable<SecuritySetting> MergeSingleSettingGroup( SecurityResponse[] responses, Func<SecurityResponse, IEnumerable<SecuritySetting>> settingExtractor) { return responses .SelectMany(settingExtractor) .GroupBy(s => s.SettingKey) .Select(group => new SecuritySetting { SettingKey = group.Key, SecuritySettingValue = group.Max(s => s.SecuritySettingValue) }); }
兼容字符串类型权限的处理
如果原securitySettingValue是字符串(而非枚举),可先定义权限优先级转换函数,再用于比较:
// 转换字符串权限为优先级数值,数值越大权限越宽松 private static int GetPermissionPriority(string permission) => permission switch { "W" => 2, "R" => 1, "H" => 0, _ => throw new ArgumentOutOfRangeException(nameof(permission), "无效的权限值") };
在合并时替换Max逻辑:
// 示例:单类型合并中替换为字符串权限处理 .Select(group => new SecuritySetting { SettingKey = group.Key, SecuritySettingValue = group.OrderByDescending(s => GetPermissionPriority(s.SecuritySettingValue)) .First() .SecuritySettingValue });
优势说明
- 完全避免手动多层嵌套循环,代码可读性更强
- LINQ内置方法经过微软优化,性能优于手动实现的遍历逻辑
- 枚举/优先级函数的使用,避免了字符串比较的潜在错误,逻辑更严谨
内容的提问来源于stack exchange,提问作者Franco Aguilera
相关产品推荐
相关产品推荐

