C# storing data in data structure - c#

I have data like..
1 -> a 10
b xyz
c 40
12 -> a 20
b os
8 -> ..............
how to store this data in data structure. which DS is suitable for it in C#.
1,12,8 are the object no. & a,b,c are the there attribute key & value pair.
it is internal file representation of .. file.
So i want to store it for further manipulation operations.

Anonymous classes and implicitly typed arrays make
code shorter by doing away with the need for class
templates and explicit types in source code. A big drawback of this feature is elements are read-only.
No additional code is missing from this example, except to paste it into your source file.
A concise, anonymous data structure
// Strongly-typed anonymous data structure.
var allData = new[] { // array of parts
new { Num = 1, Details = new[] { // each part is keyed by object num
new {KeyChar = 'a', StringValue = "10"} , // key/value pair details
new {KeyChar = 'b', StringValue = "xyz"} ,
new {KeyChar = 'c', StringValue = "40"} }
},
new { Num = 12, Details = new[] {
new {KeyChar = 'a', StringValue = "20"} ,
new {KeyChar = 'b', StringValue = "os"} }
},
new { Num = 8, Details = new[] {
new {KeyChar = 'n', StringValue = "etc..."} }
}
};
The Types are automatically inferred by your consistent data declarations and generated into IL by the C# 3.x+ compiler.
Sample Usage
iterating over your data structure and printing it ....
foreach (var part in allData) {
Console.WriteLine("Object #" + part.Num + " contains the details: ");
foreach (var detail in part.Details)
Console.WriteLine(" - key: " + detail.KeyChar + ", value: " + detail.StringValue);
}
Stipulations
var, for implicitly typed variables, cannot be used at the class scope (i.e. to make fields) - it is restricted to method scope (i.e. as local variables).
There are some things to watch out for when using anonymous types, for example: Can't return anonymous type from method? Really?
The MSDN documentation describes some additional behaviour and "Gotchas".
- Anonymous instances are read-only, so you will need a different way to store and persist modifications. This may render it useless for your requirements.
However, it was fun to include this answer as an option because I learned something new today if nothing else. :)
Edit/Update: Writable version
(modification to make an equivalent writable data structure)
An equivalent writable version of the above data structure is the following, using System.Collections.Generic;:
// Initialization (present data is read/writable)
Dictionary<int, List<Detail>> manageableData = new Dictionary<int, List<Detail>>()
{
{1, new List<Detail>() {
new Detail {KeyChar = 'a', StringValue="10"},
new Detail {KeyChar = 'b', StringValue="xyz"},
new Detail {KeyChar = 'c', StringValue="40"}
} },
{12, new List<Detail>() {
new Detail {KeyChar = 'a', StringValue="20"},
new Detail {KeyChar = 'b', StringValue="os"}
} }
};
// Can continue populating after initialization. E.g...
manageableData.Add(8, new List<Detail>() {
new Detail {KeyChar = 'n', StringValue="etc..."},
new Detail {KeyChar = 'z', StringValue="etc..."}
});
A small helper class is declared to make initialization of detail data more readable; the Detail helper class replaces what could simply be KeyValuePair<char, string>. According to taste.
public class Detail {
public char KeyChar { get; set; }
public string StringValue { get; set; }
}
... effectively allows us to use new Detail {KeyChar = 'b', StringValue="xyz"} for init of detail items instead of new KeyValuePair<char, string>('b', "xyz").
Sample Usage
iterating over your data structure and printing it ....
foreach (var part in manageableData) {
Console.WriteLine("Object #" + part.Key + " contains the details: ");
foreach (var detail in part.Value)
Console.WriteLine(" - key: " + detail.KeyChar + ", value: " + detail.StringValue);
}
Another variation on Writable data structure (less abstract)
(no unneeded abstraction - just raw collections)
Without the custom Detail class, you'd nest your dictionaries like
Dictionary<int, Dictionary<char, string>> data2 = new Dictionary<int, Dictionary<char, string>>()
{
{1, new Dictionary<char, string>() {
{'a', "10"},
{'b', "xyz"},
{'c', "40"}
} }
};
data2.Add(8, new Dictionary<char,string>() {
{'n', "etc..."},
{'z', "etc..."}
});
// SAMPLE USAGE:
// Once again, very minor changes to the mechanism of accessing the data structure:
foreach (var part in data2) {
Console.WriteLine("Object #" + part.Key + " contains the details: ");
foreach (var detail in part.Value)
Console.WriteLine(" - key: " + detail.Key + ", value: " + detail.Value);
}
Name "Aliasing" for readability
This is the plain nested dictionary scenario to store file objects and attributes.
// initialize
Dictionary<int, Dictionary<char, string>> data1 = new Dictionary<int, Dictionary<char, string>>()
{
{1, new Dictionary<char, string>() {
{'a', "10"},
{'b', "xyz"},
{'c', "40"}
}}
};
// populate
data1.Add(8, new Dictionary<char, string>() {
{'n', "etc..."},
{'z', "etc..."}
});
Making a more Descriptive/Readable Version
There are ways to make nested data structures more readable. Here's one sample to show some readability differences. Likely this isn't the smartest way because it adds a couple of Types just for the sake of aliasing but nonetheless...
This is the exact same data structure as above but using "aliased" names:
// initialize
FileObjects data2 = new FileObjects()
{
{1, new ObjectAttributes() {
{'a', "10"},
{'b', "xyz"},
{'c', "40"}
}}
};
// populate
data2.Add(8, new ObjectAttributes() {
{'n', "etc..."},
{'z', "etc..."}
});
The following "alias" definitions effectively rename the original Generics (through inheritance) to more descriptive types and hide the Type Parameters.
public class ObjectAttributes : Dictionary<char, string> { }
public class FileObjects : Dictionary<int, ObjectAttributes> { }
Likely you'd need more nested data before this type of approach becomes viable.

a Dictionary<int,Dictionary<string,string>>
Edit:
if you only have 'a' 'b' 'c' as the keys, you'd just use string[] rec = new string[3] instead of a dictionary.

Data content itself is just one aspect of data structure choice. A more important guideline is how you will create, manipulate, and access the data.
List<Dictionary<char, object>> will handle ordering if you want to access 1, 2, 3, etc.. in an ordered fashion and allow the second level to be any type of content you want.
Dictionary<int, Dictionary<string, string>> would allow you to do fast lookups of any top level 1, 2, 3, etc... and would assume that the a / 10, b / xyz, etc... are always encoded as strings.
It would help if you told us how you were using this data.

Raw structure you could use:
Dictionary<int, Dictionary<char, object>> //or
Dictionary<int, Dictionary<string, object>> //the more common construct, or
Dictionary<int, Dictionary<string, string>> //would require casting on some objects
This probably wont be optimal for your situation though, depending on how you intend to search/access this.
Depending on the meaning of your data a specific class implementation and a Dictionary implementation might work better.

Related

Why this confusing syntax exists?

I've just read this question.
If we have property of dictionary type:
public class Test
{
public Dictionary<string, string> Dictionary { get; set; } = new Dictionary<string, string>
{
{"1", "1" },
{"2", "2" },
};
}
Then we can construct object and add value to it
var test = new Test { Dictionary = { { "3", "3" } } };
Console.WriteLine(test.Dictionary.Count); // 3
And I don't understand the point why such a confusing syntax to add items exists? When looking at someone else code it's very easy to confuse it with very similarly looking
var test = new Test { Dictionary = new Dictionary<string, string> { { "3", "3" } } };
Console.WriteLine(test.Dictionary.Count); // 1
I'd be more OK with it if following would be possible (but it's not):
var dictionary = new Dictionary<string, string> { { "1", "1" } };
...
// adding a new value
dictionary = { { "2" , "2"} }; // invalid expression term '{'
So why this form of adding was needed and exists? For interviews?
The collection initializer syntax is simply a convenient way of initializing collections (including dictionaries) as part of a complex object model using an object initializer. For example:
var model = new SomeModel {
Name = "abc",
Id = 42,
SpecialMaps = {
{ "foo", "bar" },
{ "magic", "science" },
}
};
If you don't like it: just don't use it; but the equivalent with manual .Add is IMO much less elegant - a lot of things are taken care of automatically, such as only reading the property once. The longer version that actually creates the collection at the same time works very similarly.
Note that there is also an indexer variant now:
var model = new SomeModel {
Name = "abc",
Id = 42,
SpecialMaps = {
["foo"] = "bar",
["magic"] ="science",
}
};
This is very similar, but instead of using collection.Add(args); it uses collection[key] = value;. Again, if it confuses you or offends you: don't use it.
Take this example where the constructor of Thing creates a Stuff and the constructor of Stuff creates the Foo list
var thing = new Thing();
thing.Stuff.Foo.Add(1);
thing.Stuff.Foo.Add(2);
thing.Stuff.Foo.Add(3);
And now you can simplify it to the following with initializers.
var thing = new Thing
{
Stuff.Foo = { 1, 2, 3 }
};
You can only use this type of initialization for a collection without first newing up the collection when nested because the collection can exist in this case, but cannot when assigning directly to a variable.
Ultimately this type of syntactic sugar is likely added by the language designers when they see code patterns that they think can be simplified.

Change Display Format Of List<KeyValuePair<string, string>>

I am using a Xamarin.Forms Picker and it's being populated by a List<KeyValuePair<string, string>>. The issue is that it isn't displaying the way I would like.
XAML:
<Picker x:Name="VersionPicker" ItemsSource="{Binding}"/>
C#:
Dictionary<string, string> VersionDictionary = new Dictionary<string, string>()
{
{ "asv1901", "American Standard Version" },
{ "bbe", "Bible In Basic English" },
};
List<KeyValuePair<string, string>> VersionList = VersionDictionary.ToList();
VersionPicker.BindingContext = VersionList;
What it produces is like this...
[asv1901, American Standard Version]
I would like Picker to have something along these lines...
American Standard Version (asv1901)
Is there a way to do this? XAML or C# would be fine (since it's purely a visual change, I was thinking XAML or a converter might make the most sense).
A shout-out to jdweng (since he/she just did a comment and not an answer)...
Dictionary<string, string> VersionDictionary = new Dictionary<string, string>()
{
{ "asv1901", "American Standard Version" },
{ "bbe", "Bible In Basic English" },
};
// take the dictionary<string, string>, turn it into an ienumerable<keyvaluepair<string, string>>, use linq to output the contents, format a new string based on those contents, turn it into list<string>
// "Bible In Basic English (bbe)"
var VersionList = VersionDictionary.AsEnumerable().Select(x => string.Format("{0} ({1})", x.Value, x.Key)).ToList();
VersionPicker.BindingContext = VersionList;
To get that choice back to the appropriate format...
private void VersionPicker_SelectedIndexChanged(object sender, EventArgs e)
{
var selecteditem = VersionPicker.SelectedItem.ToString();
// single quotes make it type Char while double quotes make it type String
Char delimiter = '(';
// create an array from the string separated by the delimiter
String[] selecteditemparts = selecteditem.Split(delimiter);
// take off the end space
var selecteditemvalue = selecteditemparts[0].Substring(0, (selecteditemparts[0].Length - 1));
// take off the end )
var selecteditemkey = selecteditemparts[1].Substring(0, (selecteditemparts[1].Length - 1));
}
As a secondary option (and the one I ended up using)...
Dictionary<string, string> VersionDictionary = new Dictionary<string, string>()
{
{ "asv1901", "American Standard Version" },
{ "bbe", "Bible In Basic English" },
};
var VersionList = new List<string>();
// keyvaluepair is a single instance and dictionary is a collection of keyvaluepairs
foreach (KeyValuePair<string, string> version in VersionDictionary)
{
var key = version.Key.ToUpper();
var value = version.Value;
// "Bible In Basic English (BBE)"
VersionList.Add(string.Format("{0} ({1})", value, key));
}
It just makes more sense to my rather novice coding brain. I'm sure jdweng's linq example is much more concise.

C# - Adding objects dynamically (adding dynamic property names)

I'm trying to create some dynamic ExpandoObject. I've encountered a certain problem.
As I don't know what the name of these different properties in my objects should be, I can't do like this:
var list = new ArrayList();
var obj = new ExpandoObject();
obj.ID = 1,
obj.Product = "Pie",
obj.Days = 1,
obj.QTY = 65
list.Add(obj);
Let me explain my situation: I wish to get data from a random DB (I don't know which, but building a connection string from the information I get from the UI), therefore I don't know what data I need to get. This could be an example of a DB table
TABLE Sale
ID: int,
Product: nvarchar(100),
Days: int,
QTY: bigint
This could be another exmaple:
TABLE Foobar
Id: int,
Days: int
QTY: bigint
Product_Id: int
Department_Id: int
As you see, I don't know what the DB looks like (this is 100% anonymous, therefore it needs to be 100% dynamic), and the data I want to return should look like a well constructed JSON, like so:
[
{
"ID": 1,
"Product": "Pie"
"Days": 1,
"QTY": 65
},
{
"ID": 2,
"Product": "Melons"
"Days": 5,
"QTY": 12
}
]
Or, with the other example:
[
{
"ID": 1,
"Days": 2,
"QTY": 56,
"Product_Id": 5,
"Department_Id": 2
}
{
"ID": 2,
"Days": 6,
"QTY": 12,
"Product_Id": 2,
"Department_Id": 5
}
]
I've tried working with these ExpandoObjects, but can't seem to make it work, as I can't do what's illustrated in the top of this question (I don't know the names of the properties). Is there a way for me to say something like:
var obj = new ExpandoObject();
var propName = "Product";
var obj.propName = "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
Does anyone have a solution, og simply guidance to a structure, that might solve this situation?
Rather than creating an ExpandoObject or some other dynamic type, you could create a List<Dictionary<string, object>> where each Dictionary<string, object> contains the name/value pairs you want to serialize. Then serialize to JSON using Json.NET (or JavaScriptSerializer, though that is less flexible):
var list = new List<Dictionary<string, object>>();
// Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx
list.Add(new Dictionary<string, object> { { "ID", 1 }, {"Product", "Pie"}, {"Days", 1}, {"QTY", 65} });
// Build a dictionary entry incrementally
// See https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
var dict = new Dictionary<string, object>();
dict["ID"] = 2;
dict["Product"] = "Melons";
dict["Days"] = 5;
dict["QTY"] = 12;
list.Add(dict);
Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
Console.WriteLine(new JavaScriptSerializer().Serialize(list));
The first outputs:
[
{
"ID": 1,
"Product": "Pie",
"Days": 1,
"QTY": 65
},
{
"ID": 2,
"Product": "Melons",
"Days": 5,
"QTY": 12
}
]
The second outputs the same without the indentation:
[{"ID":1,"Product":"Pie","Days":1,"QTY":65},{"ID":2,"Product":"Melons","Days":5,"QTY":12}]
Use dynamic, then cast to IDictionary<string, object> to loop through your properties:
dynamic obj = new ExpandoObject();
obj.Product = "Pie";
obj.Quantity = 2;
// Loop through all added properties
foreach(var prop in (IDictionary<string, object>)obj)
{
Console.WriteLine(prop.Key + " : " + prop.Value);
}
I've made a fiddle: https://dotnetfiddle.net/yFLy2u
Now this is a solution to your question... other answers like #dbc's might be better suited to the problem (which is not the question, really)
As you can see here ExpandoObject Class, the ExpandoObject is implementing IDictionary<string, object>, so you can use that fact like
IDictionary<string, object> obj = new ExpandoObject();
var propName = "Product";
obj[propName] = "Pie"
Console.WriteLine("Let's print!: " + obj[propName]);
// Verify it's working
Console.WriteLine("Let's print again!: " + ((dynamic)obj).Product);
While I was writing the answer, I see you already got proper answer. You can use a Dictionary<string, onject> or even Tuple.
But as per your original question, you wanted to add properties dynamically. For that you can refer to other answer using ExpandoObject. This is just the same solution (using ExpandoObject to dynamically add properties) with classes similar to your code.
//example classes
public class DictKey
{
public string DisplayName { get; set; }
public DictKey(string name) { DisplayName = name; }
}
public class DictValue
{
public int ColumnIndex { get; set; }
public DictValue(int idx) { ColumnIndex = idx; }
}
//utility method
public static IDictionary<string, object> GetExpando(KeyValuePair<DictKey, List<DictValue>> dictPair)
{
IDictionary<string, object> dynamicObject = new ExpandoObject();
dynamicObject["Station"] = dictPair.Key.DisplayName;
foreach (var item in dictPair.Value)
{
dynamicObject["Month" + (item.ColumnIndex + 1)] = item;
}
return dynamicObject;
}
Ans usage example:
var dictionaryByMonth = new Dictionary<DictKey, List<DictValue>>();
dictionaryByMonth.Add(new DictKey("Set1"), new List<DictValue> { new DictValue(0), new DictValue(2), new DictValue(4), new DictValue(6), new DictValue(8) });
dictionaryByMonth.Add(new DictKey("Set2"), new List<DictValue> { new DictValue(1), new DictValue(2), new DictValue(5), new DictValue(6), new DictValue(11) });
var rowsByMonth = dictionaryByMonth.Select(item => GetExpando(item));
First part, read this blog post by C# team thoroughly.
Lets see your code
var obj = new ExpandoObject();
var propName = "Product";
var obj.propName = "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
In your code you are using var obj = new ExpandoObject();, so you are creating a statically typed object of type ExpandableObject. In the blog they specifically call out
I didn’t write ExpandoObject contact = new ExpandoObject(), because if I did contact would be a statically-typed object of the ExpandoObject type. And of course, statically-typed variables cannot add members at run time. So I used the new dynamic keyword instead of a type declaration, and since ExpandoObject supports dynamic operations, the code works
So if you rewrite your code to use dynamic obj, and add the dynamic properties as properties it should work!
But for your particular use case you better use Dictionaries as suggested above by #dbc
dynamic obj = new ExpandoObject();
obj.Product= "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie

Is there a built in type for a lookup/reverse lookup table? [duplicate]

This question already has answers here:
Bidirectional 1 to 1 Dictionary in C#
(7 answers)
Closed 8 years ago.
I'm trying to implement a Baudot character encoding. Right now, I'm using 2 dictionaries which are simply mirrors of each other:
Dictionary<char, int> Lookup = new Dictionary<char, int> {
{ ' ', 0x100100 },
{ '-', 0x011000 },
{ '/', 0x010111 },
{ '0', 0x001101 },
{ '1', 0x011101 },
...
};
Dictionary<int, char> Reverse = new Dictionary<int, char> {
{ 0x100100, ' ' },
{ 0x011000, '-' },
{ 0x010111, '/' },
{ 0x001101, '0' },
{ 0x011101, '1' },
...
};
Is there a built in type that handles this already? Something like:
var lookup = new Lookup<int, char>();
lookup.GetByKey(0x100100);
lookup.GetByValue('c');
I couldn't find anything when I searched for 'reverse lookup' or 'lookup table', everything seemed to be related to DNS or LinqToSql.
(I'm using Baudot because it's necessary for some Cospas Sarsat devices)
I think you are in need of a Bi-Directional Dictionary. There are many such implementations available. I like the one in this link though :
http://blogs.microsoft.co.il/blogs/ranw/BDirectional.txt
The only pre-requisite for this being the key and value should not be of the same type, which in your case applies.
I think that there is no such thing...
How about some extension method?
Create the first dictionary and then the second using the following method. By having two dictionaries you are having two hashtables and your access is always O(1).
public static class DictionaryExtensions
{
public static IDictionary<U, T> Reverse<T, U>(this IDictionary<T, U> dictionary)
{
var result = new Dictionary<U, T>();
foreach(var x in dictionary)
{
result[x.Value] = x.Key;
}
return result;
}
}
If it were me, I'd just have a list of pairs.
class WhateverPair
{
int Binary {get;private set;}
char TheChar {get;private set;}
public WhateverPair(int b, char c) { Binary = b; TheChar = c; }
}
Then just fill your list like you have filled your first dictionary.
List<WhateverPair> encodingtable;
char result = encodingtable.First(x=>x.binary == 0x010010).thechar;
int reverse = encodingtable.FirsT(x=>x.thechar == '1').binary;

Is this an efficient code for Multi Key Dictionary in a Method Body?

I just want to ask if:
The code below is efficient?
Is there a better way to handle this?
How to code if additional values for tablename/fieldname pair are needed?
We need to use a multi-key dictionary that contains something like (TableName, FieldName, FieldValue).
I searched some answer but the ones I found so far are not applicable to our setup. We are using 3.5 so no Tuple available yet. We are also integrating this script logic with an application that only allows coding "inside" a method body, so we are limited and cannot create a separate class/structure, etc. Our set up is C#/VS 2010.
Any help is appreciated. Thanks in advance!
Dictionary<string, Dictionary<string, string>> tableList = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> fieldList = new Dictionary<string, string>();
// add fields to field list, then add the field lists to the corresponding table list
// clear field list for next table
// values are just hardcoded here to simplify, but is being read from actual objects in the application
fieldList.Add("Field1", "abc");
fieldList.Add("Field2", "def");
fieldList.Add("Field3", "ghi");
fieldList.Add("Field4", "jkl");
tableList.Add("Table1", new Dictionary<string, string>(fieldList));
fieldList.Clear();
fieldList.Add("Field1", "xyz");
fieldList.Add("Field2", "uvw");
fieldList.Add("Field3", "rst");
tableList.Add("Table2", new Dictionary<string, string>(fieldList));
fieldList.Clear();
fieldList.Add("Field1", "123");
fieldList.Add("Field2", "456");
tableList.Add("Table3", new Dictionary<string, string>(fieldList));
fieldList.Clear();
// Display tables and corresponding fields
foreach (KeyValuePair<string, Dictionary<string, string>> fieldList4 in tableList)
{
foreach (KeyValuePair<string, string> fieldList5 in fieldList4.Value)
{
txtMessage.Text = txtMessage.Text + "\r\nTable=" + fieldList4.Key + ", Field=" + fieldList5.Key + " - " + fieldList5.Value;
}
}
// Try to find tables and fields in the lists, and list the value if found
string tableToFind = "Table2";
string fieldToFind = "Field2";
Dictionary<string, string> tableFields = new Dictionary<string, string>();
if (tableList.Keys.Contains(tableToFind) == true)
{
txtMessage.Text = txtMessage.Text = "\r\nTable=" + tableToFind + " exist in table list";
tableList.TryGetValue(tableToFind, out tableFields);
if (tableFields.Keys.Contains(fieldToFind) == true)
{
foreach(KeyValuePair<string, string> fieldData in tableFields)
{
if (fieldData.Key == fieldToFind)
{
txtMessage.Text = txtMessage.Text + "\r\nTable=" + tableToFind + ", Field=" + fieldData.Key +
" with value=" + fieldData.Value + " exist in table list";
break;
}
}
}
}
You can use the compiler to create a composite key for you: Using anonymous types.
var dictionary = new Dictionary<Object, int>();
dictionary.Add(new{Text="A", Number=1}, 1);
dictionary.Add(new{Text="A", Number=2}, 3);
dictionary.Add(new{Text="B", Number=1}, 4);
dictionary.Add(new{Text="B", Number=2}, 5);
var x = dictionary[new{Text="B", Number=2}];
C# will implement Equals and GetHashcode based on your fields. Thus you do get a key which will behave as you would expect.
There's a whole slew of problems and inefficiencies in your code.
If you're going to create multiple dictionaries, create the dictionaries directly. Don't use a separate instance to fill the values and copy from.
Never use string concatenation in a loop like that. Use a StringBuilder or other similar mechanism to build up your strings. You already have your values in a collection so using String.Join() in conjunction with LINQ would clean that up.
Your approach to get values from the dictionary is awkward to say the least. Normally you'd use TryGetValue() alone to attempt to read the key. Your code uses it incorrectly. If you are going to check if the key exists in the dictionary (using Contains()), then there's no point in using TryGetValue(). To make things worse, you did this then searched for the key manually in the inner dictionary by iterating through the key value pairs.
The typical pattern looks like this:
DictValueType value;
if (myDict.TryGetValue(key, out value))
{
// key was in the dictionary, the value is stored in the `value` variable
}
The code you have could be written much much more efficiently like this:
var tableList = new Dictionary<string, Dictionary<string, string>>
{
{ "Table1", new Dictionary<string, string>
{
{ "Field1", "abc" },
{ "Field2", "def" },
{ "Field3", "ghi" },
{ "Field4", "jkl" },
}
},
{ "Table2", new Dictionary<string, string>
{
{ "Field1", "xyz" },
{ "Field2", "uvw" },
{ "Field3", "rst" },
}
},
{ "Table3", new Dictionary<string, string>
{
{ "Field1", "123" },
{ "Field2", "456" },
}
},
};
// Display tables and corresponding fields
txtMessage.Text = String.Join("\r\n",
tableList.SelectMany(table =>
table.Value.Select(fieldList =>
String.Format("Table={0}, Field={1} - {2}",
table.Key, fieldList.Key, fieldList.Value)
)
).ToArray()
);
// (I hope you have this in a separate method)
// Try to find tables and fields in the lists, and list the value if found
string tableToFind = "Table2";
string fieldToFind = "Field2";
var builder = new StringBuilder(txtMessage.Text); // mostly useful if you have a
// lot of different strings to add
Dictionary<string, string> foundTable;
if (tableList.TryGetValue(tableToFind, out foundTable))
{
builder.AppendLine()
.Append("Table=" + tableToFind + " exist in table list");
string foundField;
if (foundTable.TryGetValue(fieldToFind, out foundField))
{
builder.AppendLine()
.AppendFormat("Table={0}, Field={1} with value={2} exist in table list",
tableToFind, fieldToFind, foundField);
}
}
txtMessage.Text = builder.ToString();
Nested dictionaries aren't a bad thing, it's a nice way to organize hierarchies of keys and values. But to keep it maintainable, you generally should encapsulate everything within another class providing methods to manipulate the data without having to manage the dictionaries directly. You can make it both efficient and maintainable. How to implement this is an exercise left to you.
I don't think so many dictionaries would be 'efficient'.
I think the best way would be to add values into the same dictionary multiple times - assuming you want to be able to index them according to one of the indicies (not all):
dictionary.Add("FField1", "xxx");
dictionary.Add("TTable1", "xxx");
Otherwise use a joining character (like '\0') if you want to index them according to all the indicies together.
dictionary.Add("Table1\0Field1", "xxx");

Categories