David Green
David Green

Reputation: 1234

How To Write A More Complex LINQ Query

Assuming I have:

public class Cluster
{
   List<Host>  HostList = new List<Host>();
}
public class Host
{
   List<VDisk> VDiskList = new List<VDisk>();
} 

public class VDisk
{
   public string Name {get; set}
}

I need all the hosts from a Cluster object that have a VDisk of a given name. I can do it with a foreach but would rather have a LINQ query. I tried a SelectMany() but it is returning the VDisk and not the Hosts. Do I need to implement a custom Comparer to do this?

Here's what I Tried:

Cluster CurrentCluster = new Cluster();

// add some hosts here

VDisk vdisk = new VDisk();
vdisk.Name="foo";

so now I want all the hosts that have a Vdisk named "foo"

this returns the vdisk, not the hosts:

CurrentCluster.Hosts.SelectMany(h => h.VDisks.Where(v => v.Name == vdisk.Name));

Upvotes: 2

Views: 1476

Answers (2)

Kaveh Shahbazian
Kaveh Shahbazian

Reputation: 13513

First you need to declare VDiskList in Host as public or internal.

Then you can use this code:

var hostList = new List<Host>();
var givenVDiskName = "sample name";

var selectedHosts = (from h in hostList
                     where h.VDiskList.Any(vd => vd.Name == givenVDiskName)
                     select h).ToList();

Upvotes: 0

David
David

Reputation: 218818

SelectMany will indeed return the inner collections, flattened into one large collection. You want your predicate to be on Hosts, not on VDisks, since what you're looking for is a list of Hosts.

This might work:

CurrentCluster.Hosts.Where(h => h.VDisks.Any(v => v.Name == vdisk.Name));

It basically says, "Return all hosts Where any of the VDisks match the condition v.Name == vdisk.Name.

I've also seen developers who don't know about Any write something like this:

CurrentCluster.Hosts.Where(h => h.VDisks.Count(v => v.Name == vdisk.Name) > 0);

Sometimes I feel there's a certain readability advantage to the latter, if one thinks that Count is a more intuitive name than Any. Both should do the job, I just prefer the former.

Upvotes: 7

Related Questions