首页 > 解决方案 > 检查数据是否包含 LINQ 中字符串列表中的值

问题描述

我是 LINQ 的新手。我只想问是否可以检查一个字段是否包含字符串列表中的值。假设我有一个如下定义的字符串列表。

 List<String> yearList = new List<string>();

 yearList.Add("2012");
 yearList.Add("2015");

我也有一堂课Member

class Member
{
    public string Name {get; set;}
    public int Year {get; set;}
    ...
}

Objectdata是一个实现的类IEnumerable<Member>

IEnumerable<Member> data = ... 

因此 data 可能是 aList<Member>或 a Member[],或任何其他表示成员对象的可枚举序列的东西。

year现在,如果该字段在我的列表中,我想获取数据years yearList

或者更准确地说:

要求:给定一个实现的对象数据,IEnumerable<Member>并给定一个yearList实现的对象,其中IEnumerable<string>字符串是一年的文本表示,给我对象data中的所有成员,其属性值的Year文本表示至少等于中的值之一yearList

例如data如下:

Name (string) | Year (int)
    Ralph     |   2012
    Rafael    |   2012
    Bea       |   2014
    Lee       |   2015

yearList是字符串 {"2012", "2015"} 的序列。我期待这样的结果

Name (string) | Year (int)
    Ralph     |   2012
    Rafael    |   2012
    Bea       |   2014
    Lee       |   2015

我尝试了以下方法,但没有奏效

 data.where(x => x.year.contains(yearList));   <--- THIS CODE NEEDS TO BE CHANGED

这在LINQ中可能吗?

标签: c#linq

解决方案


Think how you would do it with loops

You might do:

foreach(var d in data){
    if(yearList.Contains(d.year))
        ...
}

But this is different to what you wrote; what you wrote doesn't really make sense:

//data.where(x => x.year.contains(yearList));

//as a loop
foreach(var d in data){
    if(d.year.Contains(yearList))
        ...
}

"If a single year contains a list of years..."


So, then you're working with things like LINQ Where and Select, think of them as like a loop operating over the list of things, and you provide a mini-method that accepts a single parameter, of whatever is in the collection, and returns something else. LINQ will loop over the collection calling your method once per item, passing in the item. You get to choose what the item is called

This is why it helps to have plural names for collections and singular names as the argument in the mini-method (lambda).

var cars = //list of cars

cars.Where(car => car.Maker == "Ford");

Avoid using bland names like x, because it *doesn't help you keep straight, in your head, what things are. Take a look at this:

var cars = //list of cars
var seekingMakers = new []{"Ford", GM"};

cars.Where(car => seekingMakers.Any(seekingMaker => car.Maker == seekingMaker));

We've named the outer (car) and the inner (seekingMaker) to help keep them apart and remind us what they are. seekingMaker is a single string in an string array seekingMakers.


So, for your Where you have to return a boolean from your lambda, and that is used to determine whether the item in the list makes it into the output or not

var winners = //your list of people/year

winners.Where(winner => yearList.Contains(winner.Year));

You can't say winner.Year.Contains(yearList) - you could say winner.Year.IsContainedWithin(yearList) - but there's no such thing as IsContainedWithin - it's the other way round: collection.Contains(singular) - not "singular contains collection"


Now, you never said what datatype "Year" was in your list of people - maybe it's a string, in which case it makes sense why you'd have yearList as a string.. but if it's not a string, then I strongly recommend you avoid having it be a different data type, because converting it in place will clutter up your LINQ statement, and also lower performance, because C# will spend a large amount of time converting values over and over again

At any time you want to run a search against some fixed value, match the datatype of the value to the data type of the data being searched:

Do this:

var winners = //your list of people/year with INTEGER years
var years = new[]{ 2012, 2015 };

winners.Where(winner => yearList.Contains(winner.Year));

Not these:

var winners = //your list of people/year with INTEGER years
var years = new[]{ "2012", "2015" };

//don't convert the winner's Year
winners.Where(winner => yearList.Contains(winner.Year.ToString()));

//really don't parse the string years to ints over and over
winners.Where(winner => yearList.Select(stringYear => int.Parse(stringYear)).Contains(winner.Year));

If your data is coming to you as strings, convert it once:

var winners = //your list of people/year with INTEGER years

//pass every item to int.Parse and capture the result to an array you can reuse
var years = stringYearsFromElsewhere.Select(int.Parse).ToArray();

winners.Where(winner => yearList.Contains(winner.Year));

Particularly when working with LINQ, strive to find ways to make the code read like a book..


推荐阅读