Chris James
Chris James

Reputation: 11731

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

Upvotes: 1

Views: 164

Answers (5)

Eric Petroelje
Eric Petroelje

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

Amy B
Amy B

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

Joseph
Joseph

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

waterlooalex
waterlooalex

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

Daniel Br&#252;ckner
Daniel Br&#252;ckner

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

Related Questions