简体   繁体   中英

Getting distinct values from a list of objects with objects

I have a class which has two objects with in it. For example:

public class Animal
{
    public Carnivorous MeatEater { get; set; }
    public Herbivorous VegEater { get; set; }
    public Animal()
    {           
        this.MeatEater = new Carnivorous();
        this.VegEater = new Herbivorous();
    }
}

Carnivorous and Herbivorous have a Category property.

I populated this class with a list of data from my database which is stored in either MeatEater or VegEater . I need to get a distinct list of Category from both and MeatEater and VegEater combined. How can I get this list?

Thanks!

If I understood your question correctly, here you go: (this is assuming Category is a string , else you also have to overload Equals in your categories class):

var result = myList.SelectMany(GetValidCategories).Where(s => s != null)
                   .Distinct();

A needed function:

public static IEnumerable<string> GetValidCategories(Animal a)
{
    List<string> categories = new List<string>();
    if (a.MeatEater != null) categories.Add(a.MeatEater.Category);
    if (a.VegEater != null) categories.Add(a.VegEater.Catergory);
    return categories;
}

HOWEVER, this is not a good design. Animals are meat and/or veg eaters. They do not have them.

A better design would be this:

[Flags] public enum AnimalType { Carnivorous = 1, Herbivorous = 2, Ominovorous = 3 }
public class Animal
{
    public AnimalType Type { get; set; }
    public string Category { get; set; }
    //all the other members that Herbivorous + Carnivorous share,
    //so pretty much all of them really.
}

Then, it would be much easier:

var result = myList.Select(a => a.Category).Where(s => s != null).Distinct();

At least one basic approach is to first select them indpendently then union.

using System.Linq;

var query1 = (from animal in myList
    select animal.MeatEater.Category).Distinct();

var query2 = (from animal in myList
    select animal.VegEater.Category).Distinct();

var result = query1.Union(query2);

You can add all the categories from meat eaters to a list and all the categories from veg eaters to the same list if the category is not already present.

var lstCategories = new List<string>();

foreach(string category in animal.MeatEater.Category)
    if(!lstCategories.Contains(category))
        lstCategories.add(category);

foreach(string category in animal.VegEater.Category)
    if(!lstCategories.Contains(category))
        lstCategories.add(category);

so finally the lstCategories will have distinct set of combined Categories at the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM