基于PropertyInfo Name过滤CSV列的代码修改问题
解决CSV数据筛选与列名匹配问题
看起来你在处理基于属性名前缀/后缀的CSV筛选时,遇到了两个核心问题:一是用Contains做匹配时逻辑不对导致拿不到数据,二是foreach循环处理后列名没有正确过滤。我来帮你拆解解决:
1. 为什么keyIndicators.Contains(prop.Name)会返回空?
你用到的Contains是精确匹配逻辑——它只会判断prop.Name是否和keyIndicators里的某个元素完全相等,但你的需求是匹配后缀(keyIndicators是后缀列表),同理inTreatmentCohort是前缀列表,所以得用前缀/后缀匹配逻辑,而非精确匹配。
举个例子:如果keyIndicators里是"_Indicator",而你的属性名是"HeartRate_Indicator",Contains会直接返回false,自然筛选不到任何数据。
2. 正确的属性筛选逻辑
我们需要用StartsWith匹配前缀、EndsWith匹配后缀,结合Any来检查是否命中列表里的任意规则。示例代码如下:
// 假设你的数据对象类型是 YourDataModel var targetProperties = typeof(YourDataModel).GetProperties() .Where(prop => // 匹配inTreatmentCohort中的任意前缀 inTreatmentCohort.Any(prefix => prop.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) || // 匹配keyIndicators中的任意后缀 keyIndicators.Any(suffix => prop.Name.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) ) .ToList();
StringComparison.OrdinalIgnoreCase是为了忽略大小写匹配,如果你需要严格大小写校验,可以去掉这个参数。- 这个查询会一次性筛选出所有符合前缀/后缀条件的属性,避免后续循环里的重复处理。
3. 生成正确列名和数据的CSV
拿到筛选后的targetProperties后,我们可以直接用它来生成CSV的表头和数据行,这样列名自然就是符合条件的:
生成表头(列名)
var csvHeader = string.Join(",", targetProperties.Select(p => $"\"{p.Name}\"")); // 加引号避免列名含特殊字符
生成数据行
var csvRows = yourDataList.Select(item => string.Join(",", targetProperties.Select(p => { var value = p.GetValue(item)?.ToString() ?? string.Empty; return $"\"{value.Replace("\"", "\"\"")}\""; // 处理值里的引号,符合CSV规范 })) );
合并最终CSV内容
var finalCsv = string.Join(Environment.NewLine, new[] { csvHeader }.Concat(csvRows));
为什么之前foreach循环列名不对?
你之前把查询放进foreach循环后,大概率是每次循环都处理了所有属性,或者没有基于筛选后的属性集合来生成列名——而是直接用了原对象的所有属性列名。通过先一次性筛选出目标属性,再基于这个集合生成表头和数据,就能保证列名和数据完全匹配。
内容的提问来源于stack exchange,提问作者CryoFusion87
相关产品推荐
相关产品推荐

