Is there anyway to handy convert a dictionary to String? - c#

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

Related

Can we convert the style attribute value into a dictionary in C#

I need to update the style attribute values based on some calculations made in the server side, I have passed the style attribute value from client to server as string, now i need to convert it to key value pair so that i can update the style based in the key but can't convert it. any suggestions please.
value sent to server
"width:100%;height:100%;"
I need to convert this value to a dictionary in key value pairs so i can update the values based on keys or any alternate solution.
var style = "width:100%;height:70%;";
var dic = style.Split(";", StringSplitOptions.RemoveEmptyEntries)
.ToDictionary(k => k.Split(":")[0], k => k.Split(":")[1]);
// Output:
// Key: width, Value: 100%
// Key: height, Value: 70%
Or, as #DmitryBychenko offered (the only thing he forgot is to remove empty entries):
var dic = style.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Split(":"))
.ToDictionary(k => k[0], k => k[1]);
Or even Regex :)
var dic = Regex.Matches(style, "(.+?):(.+?);")
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[2]);
Find the working code of a consoleapp with the separated function that returns the dict from your string, not using LINQ (apart from the .Tolist()) so more readable and understandable for beginners maybe:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp4 {
class Program {
static void Main(string[] args) {
string mystr = "width:100%;height:100%;";
IDictionary<string, string> myDict = getDictFromString(mystr);
foreach (KeyValuePair<string, string> element in myDict) {
Console.WriteLine("Key = {0}, Value = {1}", element.Key, element.Value);
}
Console.ReadLine();
}
static private IDictionary<string, string> getDictFromString(string stringArgument) {
string[] mysubStr = stringArgument.Split(';');
IDictionary<string, string> myResultantDict = new Dictionary<string, string>();
foreach (string substr in mysubStr.ToList()) {
if (!String.IsNullOrEmpty(substr)) {
string key = substr.Split(':')[0];
string value = substr.Split(':')[1];
myResultantDict.Add(new KeyValuePair<string, string>(key, value));
}
}
return myResultantDict;
}
}
}

get TKey and TValue

i have a dictionary ...
IDictionary<int, dynamic> paragraphs = new Dictionary<int, dynamic>
{
[1] = new Nr1(),
[2] = new Nr2()
};
... first of all i don't want the value " Nr1 ", or " Nr2 ". I need to get those specifiers -> i mean the int and dynamic.
i want to make a "global foreach" so that i don't have to always specify "string", "int" or "dynamic" in the KeyValuePair part.
Thanks in advance
Well, I'll be guessing here - use var:
foreach(var item in paragraphs)
{
(...)
}

Parse String with delimiters to dictionary

I have a string formated so:
string-int,string-int,string-int
The data will always be as above, what i need to accomplish is splitting each string-int value into a dictionary. Does anyone have an efficient solution to accomplish this?
As i understand it directly splitting the string by the ',' then splitting each result by the '-' into a dictionary is ineffcient.
If you are absolutely assured that all data is correct you can use following:
split source string to the string[] by "," symbol;
for each element split it by "-" symbol;
for each resulted element (of string[][]) convert it to dictionary pair. Use first element [0] as a key and cast second element [1] to integer as a value;
Dictionary<string, int> dictionary = sourceString
.Split(',')
.Select(element => element.Split('-'))
.ToDictionary(pair => pair[0], pair => int.Parse(pair[1]));
Try following .
var input = "string-1,string2-2,string3-3";
var splittedByComma = input.Split(',').ToList();
var dictionary = new Dictionary<string, int>();
splittedByComma.ForEach(sp => dictionary.Add(sp.Split('-')[0], int.Parse(sp.Split('-')[1])));
static Dictionary<string, int> convert(string s)
{
var t = new Dictionary<string, int>();
t.Add(s.Split('-')[0], System.Convert.ToInt32(s.Split('-')[1]));
return t;
}
var t = "\"test\"-123,\"test\"-123";
var d = t.Split(',').Select(convert);

How to loop through this dictionary

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);
}

How can you change a ";" seperated string to some kind of dictionary?

I have a string like this:
"user=u123;name=Test;lastname=User"
I want to get a dictionary for this string like this:
user "u123"
name "Test"
lastname "User"
this way I can easely access the data within the string.
I want to do this in C#.
EDIT:
This is what I have so far:
public static Dictionary<string, string> ValueToDictionary(string value)
{
Dictionary<string, string> result = null;
result = new Dictionary<string, string>();
string[] values = value.Split(';');
foreach (string val in values)
{
string[] valueParts = val.Split('=');
result.Add(valueParts[0], valueParts[1]);
}
return result;
}
But to be honest I really think there is a better way to do this.
Cheers,
M.
You can use LINQ:
var text = "user=u123;name=Test;lastname=User";
var dictionary = (from t in text.Split( ";".ToCharArray() )
let pair = t.Split( "=".ToCharArray(), 2 )
select pair).ToDictionary( p => p[0], p => p[1] );
Split the string by ";".
Iterate over every element in the resulting array and split every element by "=".
Now;
dictionary.add(element[0], element[1]);
I Hope I made it clear enough.
Dictionary<string, string> d = new Dictionary<string, string>();
string s1 = "user=u123;name=Test;lastname=User";
foreach (string s2 in s1.Split(';'))
{
string[] split = s2.Split('=');
d.Add(split[0], split[1]);
}
var dictionary = new Dictionary<string, string>();
var linedValue = "user=u123;name=Test;lastname=User";
var kvps = linedValue.Split(new[] { ';' }); // you may use StringSplitOptions.RemoveEmptyEntries
foreach (var kvp in kvps)
{
var kvpSplit = kvp.Split(new[] { '=' });
var key = kvpSplit.ElementAtOrDefault(0);
var value = kvpSplit.ElementAtOrDefault(1);
dictionary.Add(key, value);
// you may check with .ContainsKey if key is already persistant
// you may check if key and value with string.IsNullOrEmpty
}
If you know for sure that there are no separator chars in your input data, the following works
string input = "user=u123;name=Test;lastname=User";
string[] fragments = input.Split(";=".ToArray());
Dictionary<string,string> result = new Dictionary<string,string>()
for(int i=0; i<fragments.Length-1;i+=2)
result.Add(fragments[i],fragments[i+1]);
It might perform slightly better than some of the other solutions, since it only calls Split() once. Usually I would go for any of the other solutions here, especially if readability of the code is of any value to you.
I think I would do it like this...
String s = "user=u123;name=Test;lastname=User";
Dictionary<string,string> dict = s.ToDictionary();
The implementation of ToDictonary is the same as yours except that I would implement it as an extension method. It does look more natural.

Categories