简体   繁体   中英

LINQ query question, needs joins

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 }});

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.

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)));
}

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.

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);
        }

    }

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

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.

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