c# Nested Dictionary, better alternative? best organize data across three classes

c#, dictionary

Solution

Typically you don't see the objects that contain values used as keys in this way. Usually you will identify some unique key on your object and use that as key and the object itself as the value. For example you could store `Person` objects in a `Dictionary` where the person's name is the key, and `Person` is the value.

Instead of nested Dictionaries, you should consider adding Collections to your objects. For example, you could add a `List<TrendyItem>` to `Trend` to maintain that relationship.

Here is an alternative way that you could organize the classes. I'm not exactly sure what the scope is of each of your collections, but this should give you another way to look at the problem.

public class Trend
{
    public string TrendName { get; set; }
    public string Description { get; set; }

    // This maintains the relationship between Trend and TrendyItem
    public List<TrendyItem> Items { get; set; }
}

public class Person
{
    public string PersonName { get; set; }
    public int PersonId { get; set; }
    public int aptitude { get; set; }

    // Each person will specifiy a "TrendyItem"
    public TrendyItem Choice { get; set; }
}

public class TrendyItem
{
    public string ItemName { get; set; }
    public string ItemId { get; set; }
}

public class TrendProfile
{
    // Change this to to a key value pair. The key will be how you uniquely identify (input) the Trend in
    //2) Input: Trend; Output: List of trendy items belonging to that trend.
    // For example TrendName
    public Dictionary<string, Trend> FavoriteTrendsOfYear;

    // Change this to to a key value pair. The key will be how you uniquely identify (input) the Person in
    // 1) Input: Person; Output: List of Person's choice on trendy items.
    // For example PersonName
    public Dictionary<string, Person> ActivePeopleThisYear;


    public List<TrendyItem> TrendyItemsThisYear; 
}

With that class structure, you can easily answer the questions in your post.

static void Main()
{
    TrendProfile trendProfile = new TrendProfile();

    trendProfile.FavoriteTrendsOfYear = new Dictionary<string, Trend> {        
        { "Pizza", new Trend() {
            TrendName = "Pizza",
            Description = "yum yum",
            Items = new List<TrendyItem> {
                new TrendyItem() {ItemName = "PotatoPizza1"},
                new TrendyItem() {ItemName = "PotatoPizza2"},
                new TrendyItem() {ItemName = "PotatoPizza3"}
            }
        }},
        { "Clothing", new Trend() {
            TrendName = "Clothing",
            Description = "ba yum",
            Items = new List<TrendyItem> {
                new TrendyItem() {ItemName = "PeplumSkirt1"},
                new TrendyItem() {ItemName = "PeplumSkirt2"},
                new TrendyItem() {ItemName = "PeplumSkirt3"}
            }
        }}
    };

    trendProfile.ActivePeopleThisYear = new Dictionary<string, Person> {
        { "Arnold Palmer", new Person() { PersonName = "Arnold Palmer", Choice = trendProfile.FavoriteTrendsOfYear["Pizza"].Items[1] }},
        { "Ken Hemingway", new Person() { PersonName = "Ken Hemingway", Choice = trendProfile.FavoriteTrendsOfYear["Clothing"].Items[2] }},
    };

    //1) Input: Person; Output: List of Person's choice on trendy items.
    string person = "Arnold Palmer";
    Console.WriteLine(trendProfile.ActivePeopleThisYear[person].Choice.ItemName);

    //2) Input: Trend; Output: List of trendy items belonging to that trend.
    string trend = "Clothing";
    foreach(TrendyItem item in trendProfile.FavoriteTrendsOfYear[trend].Items)
        Console.WriteLine(item.ItemName);

}

UPDATE

To share Trends across TrendProfiles, you could first create a "master" `List` or `Dictionary` of Trends. Then when building each of the TrendProfliles, you could pick the Trends out of the "master".

// "Master" list of trends
List<Trend> trends = new List<Trend> {
    new Trend() {
        TrendName = "Pizza",
        Description = "yum yum",
        Items = new List<TrendyItem> {
            new TrendyItem() {ItemName = "PotatoPizza1"},
            new TrendyItem() {ItemName = "PotatoPizza2"},
            new TrendyItem() {ItemName = "PotatoPizza3"}
        }
    },
    new Trend() {
        TrendName = "Clothing",
        Description = "ba yum",
        Items = new List<TrendyItem> {
            new TrendyItem() {ItemName = "PeplumSkirt1"},
            new TrendyItem() {ItemName = "PeplumSkirt2"},
            new TrendyItem() {ItemName = "PeplumSkirt3"}
        }
    }
};


TrendProfile trendProfile1 = new TrendProfile();

trendProfile1.FavoriteTrendsOfYear = new Dictionary<string, Trend> {        
    { trends[0].TrendName, trends[0] },
    { trends[1].TrendName, trends[1] }
};

TrendProfile trendProfile2 = new TrendProfile();

trendProfile2.FavoriteTrendsOfYear = new Dictionary<string, Trend> {
    { trends[1].TrendName, trends[1] }
};

Problem

Suppose There is a Trend class. ``` public class Trend{ public string TrendName { get; set; } public string Description { get; set; } } ``` e.g. ``` new Trend() { TrendName= "Pizza", Description="yum yum" }; new Trend() { TrendName= "Clothing", Description="ba yum" }; new Trend() { TrendName= "Food" }; ``` There is a Person class. ``` public class Person { public string PersonName { get; } public int PersonId { get; } public int aptitude { get; } ...... many other properties } ``` e.g. ``` new Person() { PersonName = "Arnold Palmer" }; new Person() { PersonName = "Ken Hemingway" }; ``` There is a thing class. ``` public class TrendyItem { public string ItemName { get; } public string ItemId { get; } } ``` e.g. ``` new TrendyItem() { ItemName = "PotatoPizza" } new TrendyItem() { ItemName = "PeplumSkirt" } ``` There is a TrendysOfYear class. This class already has. ``` public class TrendProfile { public List<Trend> FavoriteTrendsOfYear; public List<Person> ActivePeopleThisYear; public List<TrendyItem> TrendyItemsThisYear; } ``` For every TrendysOfYear, There will be a list of different trends, FavoriteTrendsOfYear, each person belonging to the ActivePeopleThisYear will specifiy a "TrendyItem" Given a TrendProfile, I want to be able to be able to quickly look up 1) Input: Person; Output: List of Person's choice on trendy items. 2) Input: Trend; Output: List of trendy items belonging to that trend. I've considered two ways. A) `Dictionary<Person, Dictionary<Trend, TrendyItem>>` You can get PersonsChoiceOnTrendyItem = dic[Person].Values.ToList(); but have to loop through and build new list everytime you look up TrendyItemsOfTrend. B) `Dictionary<Trend, Dictionary<Person, TrendyItem>>` vice cesra. Is it a good practice to use these custom objects for dictionary keys? Is it a good practice to use nested dictionaries? What's the best way to map items in this case? Also, not that Trend class does not have integer Id, so will have to used the string (the name of the trend is guaranteed to be unique) as key. Additional Info: properties of Trend such as TrendName and Description are editable. So i'm a little hesitant to add collection of TrendyItems to Trend class. If there is Trend, "Fashionn" in TrendProfile1 and TrendProfile2, and someone decides to change the name to "Fashion", I want both profiles to reference the same object.

Original source