Related
I’m a rookie in programming and I have a problem understanding how to print elements from a List.
In the task I’ve been given, I receive:
List<Dictionary<string,string>>() list = new
List<Dictionary<string,string>>();
list.Add(processString(string, string));
list.Add(processString(string, string));
The processStrig is a Dictionary<string,string> and the keys are the same for both records.
I tried to create a new Dictionary and then populate it with foreach:
Dictionary<string,string>() dict = new Dictionary<string, string>();
foreach (Dictionary<string,string>r in list)
{
foreach (string inner in r.Keys)
{
if (!dict.ContainsKey(inner))
{
dict.Add(inner, r[inner]);
}
}
}
and then print the new dict with another foreach, but it shows me only the first input because the keys are the same. So basically my question is how to print the both inputs? The output should look like this:
The output should look like this:
[0]
"count":"some string"
"order":"some string"
[1]
"count":"some other string"
"order":"some other string"
If you are looking for a loop solution, you can try something like this:
List<Dictionary<string, string>> list = ...
for (int i = 0; i < list.Count; ++i) {
Console.WriteLine($"[{i}]");
if (list[i] == null)
Console.WriteLine("[null]");
else
foreach (var pair in list[i])
Console.WriteLine($"\"{pair.Key}\" : \"{pair.Value}\"");
}
Let's have a method that makes you a dictionary:
public static Dictionary<string, string> MakeMeADictionary(string value1, string value2){
var d = new Dictionary<string, string>();
d["key1"] = value1;
d["key2"] = value2;
return d;
}
Let's call it twice, adding the results to a List:
var listOfDicts = new List<Dictionary<string, string>>();
listOfDicts.Add(MakeMeADictionary("first val", "second val"));
listOfDicts.Add(MakeMeADictionary("third val", "fourth val"));
Let's enumerate the list, and then each dictionary inside it:
foreach(var dict in listOfDicts){
Console.WriteLine("Enumerating a dictionary");
foreach(var keyValuePair in dict)
Console.WriteLine($"Key is: {keyValuePair.Key}, Value is: {keyValuePair.Value}");
}
Result:
Enumerating a dictionary
Key is: key1, Value is: first val
Key is: key2, Value is: second val
Enumerating a dictionary
Key is: key1, Value is: third val
Key is: key2, Value is: fourth val
Strive for variable names that make your code make sense; plurals or names of colelction types for collections, foreach vars that singularly make sense for the plural being enumerated etc.. If this were a less contrived example, and e.g. it were a List<Person> I'd call it people, perhaps, and have foreach(var person in people).. I couldn't understand your choice of r in foreach(var r in list)
I have created:
Dictionary<string, List <KeyValuePair<string,string>>> diction = new Dictionary<string, List<KeyValuePair<string,string>>>();
Later I've added to that list:
diction.Add(firststring, new List<KeyValuePair<string,string>>());
diction[firststring].Add(new KeyValuePair<string, string>(1ststringlist, 2ndstringlist));
So now, If I want to read and show on screen this dictionary, how would I do it with foreach loop ? It's like 3 dimmension syntax, don't now how to create it and access it.
Also can anyone explain how to read this part?
diction[firststring].Add
What this marks [] excatly mean? I read whole dictionary there?
thank You for answer and Your time.
Dictionaries store key / value pairs. In your case, your key type is string and value type is List <KeyValuePair<string,string>>.So when you do:
diction[firststring]
firststring is your Key and you are trying to access a List <KeyValuePair<string,string>>.Your best option is nested loops I think.if you want to display all values. For example:
foreach(var key in dict.Keys)
{
// dict[key] returns List <KeyValuePair<string,string>>
foreach(var value in dict[key])
{
// here type of value is KeyValuePair<string,string>
var currentValue = value.Value;
var currentKey = value.Key;
}
}
For printing the datastructure, try this:
// string.Join(separator, enumerable) concatenates the enumerable together with
// the separator string
var result = string.Join(
Environment.NewLine,
// on each line, we'll render key: {list}, using string.Join again to create a nice
// string for the list value
diction.Select(kvp => kvp.Key + ": " + string.Join(", ", kvp.Value)
);
Console.WriteLine(result);
In general, to loop over the values of a dictionary, you can use foreach or LINQ just like with any IEnumerable data structure. IDictionary is an IEnumerable>, so the foreach variable will be of type KeyValuePair.
The syntax diction[key] allows you to get or set the value of the dictionary stored at the index key. It's similar to how array[i] lets you get or set the array value at index i. For example:
var dict = new Dictionary<string, int>();
dict["a"] = 2;
Console.WriteLine(dict["a"]); // prints 2
If all you need to do is store rows of 3 string values each, then the data structure you are using is far too complicated.
Here's a much simpler example, based on the Tuple class:
public class Triplet : Tuple<string, string, string>
{
public Triplet(string item1, string item2, string item3) : base(item1, item2, item3)
{
}
}
So you just define a class Triplet that holds 3 strings, like above. Then you simply create a List of Triplets in your code:
// Your code here
var data = new List<Triplet>();
// Add rows
data.Add(new Triplet("John", "Paul", "George"));
data.Add(new Triplet("Gene", "Paul", "Ace"));
// Display
foreach(Triplet row in data)
{
Console.WriteLine("{0}, {1}, {2}", row.Item1, row.Item2, row.Item3);
}
and this is far simpler to read, understand, and maintain.
I have declared a dictionary like this:
Dictionary<string, KeyValuePair<string, string>> dc = new Dictionary<string, KeyValuePair<string, string>>();
now how can I loop through it? I wanted something like the following so I created that dictionary:
name1
oldValue1
newValue1
name2
oldValue2
newValue2
...
You can loop through it like so
foreach (var pair in dc)
{
string name = pair.Key;
string oldValue = pair.Value.Key;
string newValue = pair.Value.Value;
// use the values
}
But I have a feeling you're using the wrong tool for the job. It sounds to me like you really need to go ahead and define a proper class to hold the names and values, and then just work with a List<T> of that class.
foreach( KeyValuePair<string, string> kvp in dc )
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
When you loop a dictionary you use KeyValuePair that is generic. Since your dictionary contain the key as string and the value as string, this one will take also a string for both.
You can access the key with kvp.Key and the value with kvp.Value.
For your example, you are using a Dictionary of string that contain a value of KeyValuePair.
So, you can have the exact print you want with :
foreach( KeyValuePair<string, KeyValuePair<string,string>> kvp in dc )
{
Console.WriteLine(kvp.Key + " " + kvp.Value.Key + " "+ kvp.Value.Value);
}
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");
I found the default implemtation of ToString in the dictionary is not what I want. I would like to have {key=value, ***}.
Any handy way to get it?
If you just want to serialize for debugging purposes, the shorter way is to use String.Join:
var asString = string.Join(Environment.NewLine, dictionary);
This works because IDictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>.
Example
Console.WriteLine(string.Join(Environment.NewLine, new Dictionary<string, string> {
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"},
}));
/*
[key1, value1]
[key2, value2]
[key3, value3]
*/
Try this extension method:
public static string ToDebugString<TKey, TValue> (this IDictionary<TKey, TValue> dictionary)
{
return "{" + string.Join(",", dictionary.Select(kv => kv.Key + "=" + kv.Value).ToArray()) + "}";
}
How about an extension-method such as:
public static string MyToString<TKey,TValue>
(this IDictionary<TKey,TValue> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
var items = from kvp in dictionary
select kvp.Key + "=" + kvp.Value;
return "{" + string.Join(",", items) + "}";
}
Example:
var dict = new Dictionary<int, string>
{
{4, "a"},
{5, "b"}
};
Console.WriteLine(dict.MyToString());
Output:
{4=a,5=b}
Maybe:
string.Join
(
",",
someDictionary.Select(pair => string.Format("{0}={1}", pair.Key.ToString(), pair.Value.ToString())).ToArray()
);
First you iterate each key-value pair and format it as you'd like to see as string, and later convert to array and join into a single string.
No handy way. You'll have to roll your own.
public static string ToPrettyString<TKey, TValue>(this IDictionary<TKey, TValue> dict)
{
var str = new StringBuilder();
str.Append("{");
foreach (var pair in dict)
{
str.Append(String.Format(" {0}={1} ", pair.Key, pair.Value));
}
str.Append("}");
return str.ToString();
}
I got this simple answer.. Use JavaScriptSerializer Class for this.
And you can simply call Serialize method with Dictionary object as argument.
Example:
var dct = new Dictionary<string,string>();
var js = new JavaScriptSerializer();
dct.Add("sam","shekhar");
dct.Add("sam1","shekhar");
dct.Add("sam3","shekhar");
dct.Add("sam4","shekhar");
Console.WriteLine(js.Serialize(dct));
Output:
{"sam":"shekhar","sam1":"shekhar","sam3":"shekhar","sam4":"shekhar"}
If you want to use Linq, you could try something like this:
String.Format("{{{0}}}", String.Join(",", test.OrderBy(_kv => _kv.Key).Zip(test, (kv, sec) => String.Join("=", kv.Key, kv.Value))));
where "test" is your dictionary. Note that the first parameter to Zip() is just a placeholder since a null cannot be passed).
If the format is not important, try
String.Join(",", test.OrderBy(kv => kv.Key));
Which will give you something like
[key,value], [key,value],...
Another solution:
var dic = new Dictionary<string, double>()
{
{"A", 100.0 },
{"B", 200.0 },
{"C", 50.0 }
};
string text = dic.Select(kvp => kvp.ToString()).Aggregate((a, b) => a + ", " + b);
Value of text: [A, 100], [B, 200], [C, 50]
You can loop through the Keys of the Dictionary and print them together with the value...
public string DictToString(Dictionary<string, string> dict)
{
string toString = "";
foreach (string key in dict.Keys)
{
toString += key + "=" + dict[key];
}
return toString;
}
I like ShekHar_Pro's approach to use the serializer. Only recommendation is to use json.net to serialize rather than the builtin JavaScriptSerializer since it's slower.
I really like solutions with extension method above, but they are missing one little thing for future purpose - input parametres for separators, so:
public static string ToPairString<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, string pairSeparator, string keyValueSeparator = "=")
{
return string.Join(pairSeparator, dictionary.Select(pair => pair.Key + keyValueSeparator + pair.Value));
}
Example of using:
string result = myDictionary.ToPairString(Environment.NewLine, " with value: ");
What you have to do, is to create a class extending Dictionary and overwrite the ToString() method.
See you