\$\begingroup\$
\$\endgroup\$
Code
List<Element> elements = GetElementsList();
ISet<string> usedInnerElements = new HashSet<string>();
foreach (Element element in elements)
{
foreach (InnerElement innerElement in element.InnerCollection.InnerElements)
{
usedInnerElements.Add(innerElement.SomeValue);
}
}
class Element
{
public InnerCollection InnerCollection { get; set; }
}
class InnerCollection
{
public List<InnerElement> InnerElements { get; set; }
}
class InnerElement
{
public string SomeValue { get; set; }
}
This code scan inner collections of some other collection and save only unique values.
Question
Is there any way to present it in more fluent way using LINQ method syntax?
1 Answer 1
\$\begingroup\$
\$\endgroup\$
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) fromIEnumerable<IEnumerable<string>>
toIEnumerable<string>
- With
Select
we retrieve thestring
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 theIEnumerable<string>
toISet<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,
answered Jun 29, 2021 at 10:31
lang-cs