开发者

Select from a List<T>

I'm sure there's an wasy way of doing this (I'm guessing one of the extension methods?), but am struggling to find it with Google.

Basically I have a List of custom classes; I want to select some items from this into a new List where one of the properties is equal to any value in another List.

Here's a (simplified) quick example of what I'm trying to do:

public class Job
    {
        public int Number;
        publ开发者_Go百科ic string ClientCompanyName;            
    }

List<Job> lstJobs = new List<Job>();
List<Job> lstCompare = new List<Job>();

normally I would do something like:

List<Job> lstFiltered = new List<Job>();
foreach(Job jobThis in lstCompare)
{
    foreach(jobComp in lstCompare)
    {
        if(jobThis.Number = jobComp.Number)
        {
            lstFiltered.Add(jobThis);
        }
    }
}

Is there an extension method that neatens this last bit up into (ideally) a single line?

Cheers


You can use Intersect() for this:

http://msdn.microsoft.com/en-us/library/bb460136.aspx


Use Intersect.
For it to work with your custom comparison you either need to implement IEquatable<T> in your class or create a new class the implements IEqualityComparer<T> for your class and pass that to the overload of Intersect.


Jez,

You might be able to use the LINQ intersect function, or try:

var matches = from jobs in lstJobs
               join comp in lstCompare on jobs.Number equals comp.Number
               select jobs;

or LINQ syntax:

var matches = lstJobs.Join(lstCompare, jobs => jobs.Number,
                           comp => comp.Number, (jobs, comp) => jobs);

and here was reSharper's version based on your original loop:

List<Job> lstFiltered = (lstJobs.SelectMany(jobThis => lstCompare, 
                        (jobThis, jobComp) => new {jobThis, jobComp})
                        .Where(@t => @t.jobThis.Number == @t.jobComp.Number)
                        .Select(@t => @t.jobThis)).ToList();

slightly verbose, but another way to skin the cat.

[edited] as had set to new list, rather than selected elements - doh


var lstFiltered = lstJobs
        .Where(job => lstCompare.Any(item => item.Number == job.Number))
        .ToList();

The above solution works well if the number of items in the lstCompare is small. For bigger comparison lists you may want to use some hash based collection.

var compareSet = new HashSet<int>(lstCompare.Select(item => item.Number));
var lstFiltered = lstJobs
        .Where(job => compareSet.Contains(job.Number))
        .ToList();

If the comparison condition is more complex or it is needed in several places, you should create a comparer class that implements IEqualityComparer<T>. Then you could use the Intersect() method as others have already suggested. However, it is not functionally identical with the above solutions. It returns only distinct elements while my solutions return all matching elements. It may be a significant difference in some applications.

My second example can be easily changed to use IEqualityComparer<T> if necessary. The HashSet<T> takes the comparer as second parameter.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜