Reputation: 11731
Not entirely sure of a good title for this, feel free to edit it to a good one
I have an images object, which contains a list of organs which it is related to.
I want to query a list of images and find which ones have all of the organs in a list of organs.
Here is the method signature
public static IEnumerable<Image> WithOrgans(this IEnumerable<Image> qry, IEnumerable<Organ> organs)
Not really sure how to construct the linq for this, would appreciate some ideas, I haven't done linq in a while so am quite rusty!
UPDATE
Ok, so this is some sample data
dictionary.Add(7, new Image { id = 7, organs = new List<Organ> { organA, organB }});
dictionary.Add(8, new Image { id = 8, organs = new List<Organ> { organA }});
dictionary.Add(9, new Image { id = 9, organs = new List<Organ> { organC }});
Upvotes: 1
Views: 164
Reputation: 60569
Another way of doing it using Intersect:
from i in qry
where i.Organs.Intersect(organs).Count == organs.Count
select i
ETA:
From your comment, you mention you are getting a WhereListIterator back. I believe that the WhereListIterator implements IEnumerable, so you are getting back exactly what you should be getting.
If you are finding that the results are empty when they shouldn't be, you might want to check to make sure your Image class implements Equals() and GetHashCode() properly so that they can be effectively compared.
Upvotes: 10
Reputation: 110221
Just for fun:
IEnumerable<Image> result = qry
.SelectMany(i => i.Organs, (i, o) => new {i, o})
.GroupBy(x => x.o, x => x.i}
.Where(kvp => organs.Contains(kvp.Key))
.Select(kvp => kvp.Value)
.Aggregate( (z, x) => z.Intersect(x) );
With a haiku comment:
//unpack image hi-archy
//group images by organ
//filter to the list
//use the groups' values
//intersect all of those
Upvotes: 0
Reputation: 25533
Maybe like this?
var imagesWithAllOrgans =
from image in qry
where image.Organs.All(organ => organs.Contains(organ))
select image;
This assumes that organs is an enumeration of all distinct organs you wish to compare your images with.
Upvotes: 0
Reputation: 13932
Here is an idea:
Create a query for images having each organ individually, then intersect those
(rough code)
var imagesPerOrgan = organs.Select(organ => ImagesOrgans.Where(io => io.OrganId = organ.Id));
var result = null;
foreach (var item in imagesPerOrgan)
{
if (result == null)
{
result = item;
}
else
{
result = result.Intersect(result);
}
}
Upvotes: 0
Reputation: 59705
Assuming the associated organs of an image are stored in the collection Image.Organs, the following query will do the trick. It depends on your LINQ provider if some modification are required because of unsupported functions.
public static IEnumerable<Image> WithOrgans(
this IEnumerable<Image> qry, IEnumerable<Organ> organs)
{
return qry.Where(image => organs.All(organ => image.Organs.Contains(organ)));
}
Upvotes: 1