Full Time Skeleton
Full Time Skeleton

Reputation: 1740

LINQ find if nested IEnumerables contain specific values at each level of nested IEnumerable

I need to query items in three levels of nested IEnumerable to find whether I have specific items at each level of the enumeration. I've an IEnumerable of Charts containing Bands and within there Members as below.

Given that I've to check in the IEnumerable of Charts if a chart of a specific name exists, and if so within that specific chart if there's a band with a specific name within the IEnumerable of bands and finally whether within that band there's a member whose name is Z.

Is this possible with a single LINQ query or is there a better way of iterating through those records at each level and confirming that Chart X exists and within Chart X that Band Y exists and within Band Y that member Z exists?

public class chart{
   public string name {get; set;}
   public IEnumerable<Band> Bands {get; set;}
}

public class Band{
   public string name {get; set;}
   public IEnumerable<Member> Members {get; set;}
}

public class Member{
   public string name {get; set;}
   
}


Upvotes: 2

Views: 610

Answers (2)

pinkfloydx33
pinkfloydx33

Reputation: 12749

If all you need is to verify whether the combination exists, you can nest calls to Any:

var exists = charts.Any(c => 
       c.name == "chart name" && c.Bands.Any(b => 
             b.name == "band name" && b.Members.Any(m => 
                    m.name == "member name")));

if (exists) {
  Console.WriteLine("Found!");
} 

This will stop iterating once a match is found at the individual levels of nesting, at worst enumerating all sub-collections (with appropriate name) if a match is never found. The result is true/false, whereas the (currently) accepted answer will return a list of Members which is needless if all you need is verification.

If you like that form better, then changing the last Where to Any would at least avoid the extra list:

var exists = charts
  .Where(c => c.name == "chart name")
  .SelectMany(c=> c.Bands)
  .Where(b => b.name == "band name")
  .SelectMany(b=> b. Members)
  .Any(m => m.name == "member name");

Upvotes: 0

Eugene
Eugene

Reputation: 1533

charts
.Where(c => c.name == "Chart_name")
.SelectMany(c=> c.Bands)
.Where(b => b.name == "Band_name")
.SelectMany(b=> b. Members)
.Where(m => m.name == "member_name")
.ToList()

Upvotes: 2

Related Questions