Reputation: 1234
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
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
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