简体   繁体   English

检查数据是否包含来自 LINQ 字符串列表的值

[英]Check if data contains a value from List of string in LINQ

I am new to LINQ.我是 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 :我也有一个班级Member

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

Object data is of a class that implements IEnumerable<Member> :对象data属于实现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.因此 data 可以是List<Member>Member[] ,或任何其他表示 Member 对象的可枚举序列的东西。

Now I want to get the data if the year field is in my list of years yearList .现在,如果year字段在我的年份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 .要求:给定一个实现IEnumerable<Member>的对象数据,并给定一个实现IEnumerable<string>的对象yearList ,其中字符串是年份的文本表示,给我对象data中具有值的所有成员属性Year具有至少等于yearList一个值的文本表示。

For example data is as follows:例如data如下:

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

and yearList is the sequence of strings {"2012", "2015"}. yearList是字符串 {"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?这在 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 Where 和 Select 之类的东西,将它们视为对事物列表进行操作的循环,并且您提供了一个接受单个参数的迷你方法,无论是集合中的什么,以及返回别的东西。 LINQ will loop over the collection calling your method once per item, passing in the item. LINQ 将循环遍历每个项目一次调用您的方法的集合,并传入该项目。 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).这就是为什么在迷你方法 (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.避免使用像x这样平淡无奇的名字,因为它*不能帮助你在头脑中保持清醒,知道事情是什么。 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.我们命名了外部( car )和内部( seekingMaker )以帮助将它们分开并提醒我们它们是什么。 seekingMaker is a single string in an string array seekingMakers . seekingMaker是字符串数组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所以,对于你的Where你必须从你的 lambda 返回一个布尔值,它用于确定列表中的项目是否进入输出

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"你不能说winner.Year.Contains(yearList) ——你可以说winner.Year.IsContainedWithin(yearList) ——但是没有IsContainedWithin这样的东西——它是相反的: collection.Contains(singular) ——不是“singular”包含集合"


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现在,您从未说过您的人员列表中的数据类型“Year”是什么 - 也许它是一个字符串,在这种情况下,为什么您将yearList作为字符串是yearList的..但如果它不是字符串,那么我强烈建议你避免让它成为不同的数据类型,因为就地转换它会使你的 LINQ 语句变得混乱,也会降低性能,因为 C# 将花费大量时间一遍又一遍地转换值

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..特别是在使用 LINQ 时,努力寻找方法让代码读起来像一本书。

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

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