I am new to LINQ. I just want to ask if it is possible to check if a field contains a value from a list of string. Say I have a list of string as defined below.
List<String> yearList = new List<string>();
yearList.Add("2012");
yearList.Add("2015");
I also have a class Member
:
class Member
{
public string Name {get; set;}
public int Year {get; set;}
...
}
Object data
is of a class that implements IEnumerable<Member>
:
IEnumerable<Member> data = ...
So data may be a List<Member>
or a Member[]
, or anything else that represents an enumerable sequence of Member objects.
Now I want to get the data if the year
field is in my list of years yearList
.
Or to be more precise:
Requirement : Given an object data, that implements IEnumerable<Member>
, and given an object yearList
, which implements IEnumerable<string>
, where the string is a textual representation of a year, give me all Members in object data
that have a value of property Year
that has a textual representation that equals at least one of the values in yearList
.
For example data
is as follows:
Name (string) | Year (int)
Ralph | 2012
Rafael | 2012
Bea | 2014
Lee | 2015
and yearList
is the sequence of strings {"2012", "2015"}. I am expecting a result like
Name (string) | Year (int)
Ralph | 2012
Rafael | 2012
Bea | 2014
Lee | 2015
I tried the following, but that didn't work
data.where(x => x.year.contains(yearList)); <--- THIS CODE NEEDS TO BE CHANGED
Is that possible in 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..
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.