If we can assume that none of the values can be null
then the simplest solution I can think of:
ISet<string> usedInnerElements = elements
.SelectMany(coll => coll.InnerCollection.InnerElements
.Select(elem => elem.SomeValue))
.Distinct()
.ToHashSet();
- With
SelectMany
we are reducing the dimensions (flattening) from IEnumerable<IEnumerable<string>>
to IEnumerable<string>
- With
Select
we retrieve the string
value from its wrapper class
- With
Distinct
we are making sure that we are getting rid of from all duplicates
- With
ToHashSet
we simply convert the IEnumerable<string>
to ISet<string>
Test Input:
var elements = new List<Element>
{
new Element
{
InnerCollection = new InnerCollection
{
InnerElements = new List<InnerElement>
{
new InnerElement { SomeValue = "A" },
new InnerElement { SomeValue = "C" },
new InnerElement { SomeValue = "E" },
}
}
},
new Element
{
InnerCollection = new InnerCollection
{
InnerElements = new List<InnerElement>
{
new InnerElement { SomeValue = "E" },
new InnerElement { SomeValue = "A" },
new InnerElement { SomeValue = "B" },
}
}
}
};
...
Console.WriteLine(string.Join(",", usedInnerElements));
Test output:
A,C,E,B
If you have to deal with null values then the query might look like this:
ISet<string> usedInnerElements = elements
.Where(coll => coll != null
&& coll.InnerCollection != null
&& coll.InnerCollection.InnerElements != null)
.SelectMany(coll => coll.InnerCollection.InnerElements
.Where(elem => elem != null)
.Select(elem => elem.SomeValue))
.Distinct()
.ToHashSet();
Test input
var elements = new List<Element>
{
null,
new Element
{
InnerCollection = null
},
new Element
{
InnerCollection = new InnerCollection
{
InnerElements = null
}
},
new Element
{
InnerCollection = new InnerCollection
{
InnerElements = new List<InnerElement>
{
new InnerElement { SomeValue = "E" },
new InnerElement(),
null
}
}
}
};
Test output
E,