简体   繁体   中英

C# Make List of dictionaries in List dynamically and populate/retrieve values

I read a parameters file who has sections and under each section a parameter, an equal sign and a value. For example:

[users]
Nick=twelve
John=eleven
Mary=twentynine

[stations]
pc1=on
pc2=on
pc3=off
pc4=off

[grades]
a=distinction
b=good
c=pass

etc..

I am trying to make a List of Dictionaries, since by definition I do not have repetitions of parameters' names (for example, parameter "pc1" can appear in any, but only one, section - for example above, it exists in section "[stations]" etc.) and populate as well as retrieve the data.

For example:

MyList.Add(new Dictionary<string, string>()); // "users" - how do I name the dictionary dynamically, as I read the section name?
MyList.Add(new Dictionary<string, string>()); // "stations"

etc.

The objective I am trying to achieve, is to query the list, knowing the dictionary name and the key, and retrieve the value if the key exists.

string JohnCode = MyList("users", "John")    //if key "John" exists in users Dictionary

NOTE: I do NOT know beforehand the names and how many sections are in my data. All I know is that sections are in brackets, ie [namehere] and then always follow key-value pairs as above.. Assume every key-pair is a string.

Can you help me? Thank you in advance.

I'm going to assume that your section and keys only allow certain characters. Use that to your advantage and make a single Dictionary where the Key is the combination of the file's section and key.

In this example, I'll use a pipe | to separate the segments in the Dictionary Key.

var data = new Dictionary<string, string>();
data.Add("users|Nick", "twelve");
//...
data.Add("stations|pc1", "on");
//...
data.Add("grades|a", "distinction");
//...

Now when you want to lookup an entry, you lookup by both section and key ("users|Nick").

This however requires all entries to be part of a section. If you need to, as you read the ini file you can keep a seperate list of the section names to assist you with doing lookups later.


While it's a bit more expensive than having individual Dictionaries per section, you can still query the data.

To get a distinct list of all sections:

var sectionNames = data
    .Select(x => x.Key.Split('|')[0])
    .Distinct();

To get all entries in a section

var sectionName = "users";
var entriesInUsersSection = data
    .Where(x => x.Key.StartsWith(sectionName + "|"));

And more Linq manipulations are possible.

If you want a unique Dictionary<string, string> to store the values of each section as indicated in the comments on another answer, is there any reason you have to use a List<Dictionary<string, string>> ? Because it seems like you'd be able to solve this with a Dictionary<string, Dictionary<string, string>> .

The key of the Dictionary<string, Dictionary<string, string>> is the section name. The value would be a Dictionary<string, string> containing the values under that section.

Dictionary<string, Dictionary<string, string>> sections = 
    new Dictionary<string, Dictionary<string, string>>();

sections.Add("users", new Dictionary<string, string>>());
sections.Add("stations", new Dictionary<string, string>>());
sections["users"].Add("Nick", "twelve");
sections["stations"].Add("pc1", "on"); 

string Nick = sections["users"]["Nick"]; // Nick = "twelve"
string pc1 = sections["stations"]["pc1"]; // pc1 = "on"

You could use an extension method to Dictionary<string, Dictionary<string, string>> to handle searching safely. For example:

public static class IniExtensions
{
    public static bool TryGetSectionValue(
        this Dictionary<string, Dictionary<string, string>> src,
        string section, string key, out string value)
    {
        value = null;
        if (src.TryGetValue(section, out Dictionary<string, string> sectionValues))
        {
            return sectionValues.TryGetValue(key, out value);
        }
        return false;
    }
}

Dictionary<string, Dictionary<string, string>> sections = 
    new Dictionary<string, Dictionary<string, string>>();

sections.Add("users", new Dictionary<string, string>>());
sections.Add("stations", new Dictionary<string, string>>());
sections["users"].Add("Nick", "twelve");
sections["stations"].Add("pc1", "on"); 

// This returns true, and the Nick variable will have a value of "twelve"
sections.TryGetSectionValue("users", "Nick", out string Nick);

// this returns false, and the value variable has a value of null
sections.TryGetSectionValue("No Section", "Nick", out string value);

// this returns false, and the John variable has a value of null
sections.TryGetSectionValue("users", "John", out string John);

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