I've got a class with many string arrays. I'd like to have one generic function which can get me a unique List<string>
for a given property. Example:
public class Zoo
{
string Name { get; set;}
string[] Animals { get; set;}
string[] Zookeepers { get; set;}
string[] Vendors { get; set;}
}
I'd like to have a generic function that will get me a distinct List<string>
of Animals in List? I want this to be generic, so I can also get a distinct list of Zookeepers and Vendors.
I've been trying this, but it doesn't compile:
public static List<string> GetExtendedList(Func<Zoo, string[]> filter)
{
var Zoos = QueryZoos(HttpContext.Current);
return Zoos.Where(z => z.Type == "Active")
.SelectMany(filter)
.Distinct()
.OrderBy(s => s);
}
Note: this is related to two questions I've asked before, but I'm having trouble merging the information. I previously asked how to query using SelectMany (SO 1229897) and separately asked how to write a generic function which gets a list using Select rather than SelectMany (SO 1278989).
"Each Zoo"
click
Suppose you had a list of zoo's:
List<Zoo> zooList = GetZooList();
Then, if you wanted distinct animals from all the zoos, you would apply SelectMany in this way:
List<string> animalList = zooList
.SelectMany(zoo => zoo.animals)
.Distinct()
.ToList();
And If you commonly did this task and wanted one function to wrap these three calls, you could write such a function this way:
public static List<string> GetDistinctStringList<T>(
this IEnumerable<T> source,
Func<T, IEnumerable<string>> childCollectionFunc
)
{
return source.SelectMany(childCollectionFunc).Distinct().ToList();
}
Which would then be called:
List<string> animals = ZooList.GetDistinctStringList(zoo => zoo.animals);
And for the code sample that doesn't compile (for which you've given no error message), I deduce you need to add a ToList():
.OrderBy(s => s).ToList();
The other problem (why the type argument can't be inferred) is that string[]
doesn't implement IEnumerable<string>
. Change that type parameter to IEnumerable<string>
instead of string[]
The best way would be to create a HashSet<String>
for each String[]
- this would filter out all duplicates.
Since HashSet<T>
has a constructor that accepts an IEnumerable<T>
you could simply instantiate a HashSet<T>
by passing each of your arrays into the constructor. The resulting HashSet<T>
would be the distinct list of Strings
. While this is not a List<String>
like you requested, HashSet<T>
does implement ICollection<T>
so many of the methods you would need may be available.
static ICollection<String> GetDistinct(IEnumerable<String> sequence)
{
return new HashSet<String>(sequence);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With