简体   繁体   English

使用 Linq 根据条件过滤对象列表

[英]Using Linq to Filter a List of Objects based on a Condition

I am solving an issue where I want to remove unwanted objects from a list List<RegionData> as a result of a region name condition .我正在解决一个问题,我想从列表List<RegionData>删除不需要的对象作为区域名称条件的结果。 As an entry input I receive var data , which contains a List<CasesDto> .作为条目输入,我收到var data ,其中包含List<CasesDto> One item CasesDto corresponds to all region-based data received on one particular date .一项CasesDto对应于在一个特定日期收到的所有基于区域的数据。

These are two of my classes that I am using as an example:这些是我用作示例的两个类:

public class CasesDto
{    
    public DateTime Date {get; set;}

    public List<RegionData> Region {get; set;}
}

and

public class RegionData
{
    public string RegionName {get; set;}

    public int DailyActiveCases {get; set;}

    public int DeceasedToDate {get; set;}
}

This is the current output example (I only included two dates (= two CasesDto) for easy-to-view purpose) where region is not taken into consideration:这是当前的输出示例(为了便于查看,我只包含了两个日期(= 两个 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
            }
        ]
    }
]

This is the output I would want if regionName="ce" is applied:如果应用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
            }
        ]
    }
]

I would like to solve this problem with lambda functions .我想用lambda 函数解决这个问题。

My attempt:我的尝试:

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

However, I receive a mismatch in return type.但是,我收到的返回类型不匹配。 How can I access RegionData model and select only a region item (based on region identifier) that I want?如何访问 RegionData 模型并仅选择我想要的区域项(基于区域标识符)?

So you have an enumerable sequence of CasesDtos (plural noun), where every CasesDto (singular noun) has at least properties Date and Region .所以你有一个CasesDtos (复数名词)的可枚举序列,其中每个CasesDto (单数名词)至少有属性DateRegion

Region is an enumerable sequence of RegionDatas . Region 是一个可枚举的RegionDatas序列。 Every RegionData has several properties, among which a property RegionName .每个 RegionData 都有几个属性,其中一个属性RegionName

I think you've described the following requirement:我认为您已经描述了以下要求:

Requirement: given a string value for regionName , and a sequence of CasesDtos , give me the Date and the RegionData of every CasesDto that has at least one RegionData with a value for property RegionName that equals regionName .要求:给定一个regionName的字符串值和一系列CasesDtos ,给我每个CasesDtoDateRegionData ,这些RegionData至少有一个RegionData ,其属性RegionName的值等于regionName

You didn't tell what you want if a CasesDto has two RegionData with the correct RegionName:如果 CasesDto 有两个具有正确 RegionName 的 RegionData,您没有告诉您想要什么:

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

casesDto has two RegionDatas with a matching RegionName. caseDto 有两个具有匹配 RegionName 的 RegionData。 What do you want in your end result: only the Date and one of the RegionDatas?您希望最终结果是什么:只有日期和 RegionData 之一? which one?哪一个? Or do you want all RegionDatas with a matching RegionName?或者你想要所有具有匹配 RegionName 的 RegionDatas?

Anyway, the solution is:总之,解决办法是:

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());
             

In words: for every CasesDto in casesDtos, make one new object with two properties: the Date of the CasesDto, and a property Region which contains the RegionDatas of this CasesDto that have a matching RegionName.换句话说:对于casesDtos 中的每个CasesDto,创建一个具有两个属性的新对象:CasesDto 的日期和一个属性Region,该属性包含具有匹配RegionName 的此CasesDto 的RegionDatas。 From this Select result, keep only those object that have at least one element in list Region.从这个 Select 结果中,只保留那些在列表 Region 中至少有一个元素的对象。

    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);
        }
    });

Somewhat simplified to save me some time.稍微简化以节省我一些时间。 Using ForEach we enumerate over the list and check if we have a region with given regionnames.使用 ForEach 我们枚举列表并检查我们是否有一个具有给定区域名称的区域。 If so we filter the current list to only contain the correct regions and append this result to a new list.如果是这样,我们过滤当前列表以仅包含正确的区域并将此结果附加到新列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM