3

I have two List of two different custom types. Both types share 2 common properties.

For example:

List<foo>;
List<bar>;

They both have properties, for example, named Name and Age.

I want to return a new List containing all bar objects, where the Name and Age properties of bar are present in any of the foo objects. What would be the best way to do this?

Thanks

3 Answers 3

11

Assuming the shared properties implement equality etc properly, you might want to do something like:

// In an extensions class somewhere. This should really be in the standard lib.
// We need it for the sake of type inference.
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items)
{
    return new HashSet<T>(items);
}

var shared = foos.Select(foo => new { foo.SharedProperty1, foo.SharedProperty2 })
                 .ToHashSet();

var query = bars.Where(bar => shared.Contains(new { bar.SharedProperty1,
                                                    bar.SharedProperty2 }));

The other options using joins will certainly work - but I find this clearer for the expressing the idea that you only want to look at each bar entry once, even if there are several foo items with that property.

Sign up to request clarification or add additional context in comments.

4 Comments

HashSet is the right tool for this if there are many foos and you want it to run fast.
Thanks Jon. They don't currently implement equality. By this do you mean overriding Equals and GetHashCode?
@Darren: Yes. Of course, the default implementation may be good enough - it depends if you want any custom sort of equality.
@Jon, thanks. The datasets may get quite large, so I think this is probably the way to go.
3

Sounds like you need a join:

var fooList = new List<foo>();
var barList = new List<bar>();

// fill the lists

var results = from f in fooList
              join b in barList on 
                  new { f.commonPropery1, f.commonProperty2 }
                  equals 
                  new { b.commonProperty1, commonProperty2 = b.someOtherProp }
              select new { f, b };

Comments

1

Any should work if it's irrelevant how many foo's match:

var selectedBars = bars.Where(bar => 
                                foos.Any(foo => foo.Property1 == bar.Property1 
                                             && foo.Property2 == bar.Property2));

If all foos should match use All

var selectedBars = bars.Where(bar => 
                                foos.All(foo => foo.Property1 == bar.Property1 
                                             && foo.Property2 == bar.Property2));

If the list of foos is large use a HashSet as pointed out in John Skeets answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.