The common LINQ function is SelectMany with Func as a parameter.

I have a class with many string arrays. I would like to have one universal function that can give 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 would like to have a generic function that will give me an excellent List<string> Animals in a list? I want this to be generic, so I can also get a separate list of Zookeepers and Vendors.

I tried this, but it does not 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 due to two questions that I asked before, but I had problems with combining information. I previously asked a query using SelectMany (SO 1229897) and separately asked how to write a generic function that receives a list using Select, not SelectMany (SO 1278989) .

+4
source share
3 answers

"Every zoo"

click

Suppose you have a list of zoos:

 List<Zoo> zooList = GetZooList(); 

Then, if you want some great animals from all the zoos, you would apply SelectMany this way:

 List<string> animalList = zooList .SelectMany(zoo => zoo.animals) .Distinct() .ToList(); 

And if you usually did this task and wanted one function to wrap these three calls, you can write such a function as follows:

 public static List<string> GetDistinctStringList<T>( this IEnumerable<T> source, Func<T, IEnumerable<string>> childCollectionFunc ) { return source.SelectMany(childCollectionFunc).Distinct().ToList(); } 

which will then be called:

 List<string> animals = ZooList.GetDistinctStringList(zoo => zoo.animals); 

And for sample code that does not compile (for which you did not specify an error message), I output to you that you need to add ToList ():

 .OrderBy(s => s).ToList(); 

Another problem (why the type argument cannot be inferred) is that string[] does not implement IEnumerable<string> . Change this parameter to IEnumerable<string> instead of string[]

+19
source

The best way is to create a HashSet<String> for each String[] - this will filter out all duplicates.

Since HashSet<T> has a constructor that accepts IEnumerable<T> , you can simply create an instance of HashSet<T> by passing each of your arrays to the constructor. The resulting HashSet<T> will be a great list of Strings . Although this is not a List<String> , as you requested, HashSet<T> implements ICollection<T> , so many of the methods you need may be available.

 static ICollection<String> GetDistinct(IEnumerable<String> sequence) { return new HashSet<String>(sequence); } 
+1
source

Maybe I miss what you mean, but just ...

 List<String> distinctAnimals = zoo.Animals.Distinct().ToList(); 

will do what you ask, I assume that you mean something else?

Edit: If you have a list of zoos, but you want some great animals, then choose a lot of the right things to use, IMO its easier with the declarative linq syntax ...

 List<String> animals = (from z in zoos from s in z.Animals select s).Distinct().ToList(); 
+1
source

All Articles