使用Linq根据条件筛选对象列表



我正在解决一个问题,我想从列表List<RegionData>中删除不需要的对象,因为地区名称条件.作为输入,我接收到var data,其中包含List<CasesDto>。一项CasesDto对应于在一个特定日期上接收到的所有基于区域的数据.

这是我举的两个类的例子:

public class CasesDto
{    
public DateTime Date {get; set;}
public List<RegionData> Region {get; set;}
}

public class RegionData
{
public string RegionName {get; set;}
public int DailyActiveCases {get; set;}
public int DeceasedToDate {get; set;}
}

这是当前的输出示例(为了便于查看,我只包含了两个日期(=两个CasesDto)),其中区域不是考虑:

[
{
"date": "2021-05-22T00:00:00",
"region": [
{
"regionName": "ce",
"dailyActiveCases": 615,
"deceasedToDate": 568
},
{
"regionName": "kk",
"dailyActiveCases": 170,
"deceasedToDate": 197
},
{
"regionName": "kp",
"dailyActiveCases": 278,
"deceasedToDate": 166
}
]
},
{
"date": "2021-05-23T00:00:00",
"region": [
{
"regionName": "ce",
"dailyActiveCases": 613,
"deceasedToDate": 570
},
{
"regionName": "kk",
"dailyActiveCases": 167,
"deceasedToDate": 197
},
{
"regionName": "kp",
"dailyActiveCases": 277,
"deceasedToDate": 166
}
]
}
]

如果regionName="ce">应用:

[
{
"date": "2021-05-22T00:00:00",
"region": [
{
"regionName": "ce",
"dailyActiveCases": 615,
"deceasedToDate": 568
}
]
},
{
"date": "2021-05-23T00:00:00",
"region": [
{
"regionName": "ce",
"dailyActiveCases": 613,
"deceasedToDate": 570
}
]
}
]

我想用lambda函数来解决这个问题.

我的尝试:

data = data.ForEach(x => x.Region.Where(t => t.RegionName == region)).ToList();

但是,返回类型不匹配。如何访问RegionData模型并仅选择我想要的区域项(基于区域标识符)?

var cases = new List<CasesDto>{
new CasesDto{
Date = DateTime.Now,
Region = new List<RegionData> {
new RegionData{
RegionName = "CE"
},
new RegionData{
RegionName = "DE"
}
}
},
new CasesDto{
Date = DateTime.Now.AddDays(10),
Region = new List<RegionData> {             
new RegionData{
RegionName = "DE"
}
}
}
};


var filteredCases = new List<CasesDto>();
var regionName = "CE";
cases.ForEach(c => {
if(c.Region.Any(x => x.RegionName == regionName)){
c.Region = c.Region.Where(x => x.RegionName == regionName).ToList();
filteredCases.Add(c);
}
});

为了节省时间,有些简化了。使用ForEach对列表进行枚举,并检查是否有具有给定区名的区域。如果是,我们过滤当前列表,只包含正确的区域,并将此结果附加到新列表中。

所以你有一个CasesDtos(复数名词)的可枚举序列,其中每个CasesDto(单数名词)至少具有DateRegion的属性。

Region是RegionDatas的可枚举序列。每个RegionData都有几个属性,其中一个属性是RegionName

我想你已经描述了以下要求:

要求:给定regionName的字符串值和CasesDtos的序列,给我DateRegionData的每个CasesDto,至少有一个RegionData,属性RegionName的值等于regionName

你没有告诉你想要什么,如果一个CasesDto有两个RegionData与正确的RegionName:

string regionName = "CA";
var casesDto = new CasesDto
{
Date = ...
Region = new List<RegionData>()
{
new RegionData()
{
RegionName = "CA",
...
},
new RegionData()
{
RegionName = "CA",
...
}
}
}

casesDto有两个regiondata和一个匹配的RegionName。您想要的最终结果是什么:只有Date和一个regiondata ?哪一个?还是希望所有的regiondata都具有匹配的RegionName?

无论如何,解决方案是:

string regionName = "CA";
IEnumerable<CasesDto> casesDtos = ...
// from every CasesDto, make one object, containing the Date, and a property 
// Region, which contains only those RegionDatas that have a value for property 
// RegionName that equals regionName
var result = casesDtos.Select(casesDto => new
{
Date = casesDto.Date,
// keep only those Regions that have a matching RegionName:
Region = casesDto.Region
.Where(region => region.RegionName == regionName)
.ToList(),
}
// From this selection, keep only those object that have at least one Region:
.Where(casesDto => casesDto.Region.Any());

换句话说:对于casesDtos中的每个CasesDto,创建一个具有两个属性的新对象:CasesDto的Date,以及包含该CasesDto具有匹配RegionName的regiondata的Region属性。从这个Select结果中,只保留那些在列表区域中至少有一个元素的对象。