Most efficient Dictionary<K,V>.ToString() with formatting?
Solution 1
I just rewrote your version to be a bit more generic and use StringBuilder
:
public string DictToString<T, V>(IEnumerable<KeyValuePair<T, V>> items, string format)
{
format = String.IsNullOrEmpty(format) ? "{0}='{1}' " : format;
StringBuilder itemString = new StringBuilder();
foreach(var item in items)
itemString.AppendFormat(format, item.Key, item.Value);
return itemString.ToString();
}
Solution 2
public string DictToString<TKey, TValue>(Dictionary<TKey, TValue> items, string format)
{
format = String.IsNullOrEmpty(format) ? "{0}='{1}' " : format;
return items.Aggregate(new StringBuilder(), (sb, kvp) => sb.AppendFormat(format, kvp.Key, kvp.Value)).ToString();
}
Solution 3
This method
public static string ToFormattedString<TKey, TValue>(this IDictionary<TKey, TValue> dic, string format, string separator)
{
return String.Join(
!String.IsNullOrEmpty(separator) ? separator : " ",
dic.Select(p => String.Format(
!String.IsNullOrEmpty(format) ? format : "{0}='{1}'",
p.Key, p.Value)));
}
used next way:
dic.ToFormattedString(null, null); // default format and separator
will convert
new Dictionary<string, string>
{
{ "a", "1" },
{ "b", "2" }
};
to
a='1' b='2'
or
dic.ToFormattedString("{0}={1}", ", ")
to
a=1, b=2
Don't forget an overload:
public static string ToFormattedString<TKey, TValue>(this IDictionary<TKey, TValue> dic)
{
return dic.ToFormattedString(null, null);
}
You can use generic TKey
/TValue
because any object has ToString()
which will be used by String.Format()
.
And as far as IDictionary<TKey, TValue>
is IEnumerable<KeyValuePair<TKey, TValue>>
you can use any. I prefer IDictionary for more code expressiveness.
Solution 4
Format dictionary in one line with Linq and string.Join() (C# 6.0):
Dictionary<string, string> dictionary = new Dictionary<string, string>()
{
["key1"] = "value1",
["key2"] = "value2"
};
string formatted = string.Join(", ", dictionary.Select(kv => $"{kv.Key}={kv.Value}")); // key1=value1, key2=value2
You can create simple extension method like this:
public static class DictionaryExtensions
{
public static string ToFormatString<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, string format = null)
{
format = string.IsNullOrEmpty(format) ? "{0}='{1}'" : format;
return string.Join(", ", dictionary.Select(kv => string.Format(format, kv.Key, kv.Value)));
}
}
Solution 5
Sligtly improved version of the other answers, using extension methods and default parameters, and also wrapping key/value pairs in {}:
public static string ItemsToString<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> items, string format = "{0}='{1}' ")
{
return items
.Aggregate(new StringBuilder("{"), (sb, kvp) => sb.AppendFormat(format, kvp.Key, kvp.Value))
.Append('}')
.ToString();
}
The method can then be called directly from the dictionary/enumerable:
string s = myDict.ItemsToString()
Related videos on Youtube
Armstrongest
Front end work, Back end work. Cool kids call it the full stack. Ever curious developer of fine web stuff on the internets. "You can't work on the web and not be strive for polyglotism."
Updated on March 02, 2020Comments
-
Armstrongest about 4 years
What's the most efficient way to convert a Dictionary to a formatted string.
e.g.:
My method:
public string DictToString(Dictionary<string, string> items, string format){ format = String.IsNullOrEmpty(format) ? "{0}='{1}' " : format; string itemString = ""; foreach(var item in items){ itemString = itemString + String.Format(format,item.Key,item.Value); } return itemString; }
Is there a better/more concise/more efficient way?
Note: the Dictionary will have at most 10 items and I'm not committed to using it if another similar "key-value pair" object type exists
Also, since I'm returning strings anyhow, what would a generic version look like?
-
Gabe over 13 yearsI think that's pretty efficient; just change it to use a
StringBuilder
instead string concatenation and you should be set.
-
-
Lee over 13 yearsThis won't work as you think -
IDictionary<string, string>
is not compatible withIDictionary<string, object>
- you could make the value generic however. -
Gabe over 13 yearsI originally meant generic in the "uses IDictionary instead of Dictionary" sense, but I was already doing what you suggested as you posted yours.
-
James Curran over 13 years@Gabe: The thing is I don't think you can pass a
Dictionary<string, string>
as aIDictionary<string,object>
-
Gabe over 13 yearsYou're right; I just posted before I was really done writing the damn thing.
-
abatishchev over 13 yearsI think you can use
IDictionary
-
abatishchev over 13 years@Gabe, @James:
StringBuilder
has next overload:AppendFormat(string, object, object)
so you can use both generic - key and value -
James Curran over 13 years@abatishchev; I wasn't worried about StringBuilder. Gabe had changed the signature of the function.
-
Lee over 13 yearsThat looks fine, +1 for using
IEnumerable<T>
. -
Dan Tao over 13 yearsNitpick: The fact that string concatenation using the
+
operator creates newstring
objects in memory is actually unrelated to the fact that thestring
type is immutable (though both are true). -
Skurmedel over 13 years@Dan Tao: I'm a bit thick at the moment, could you elaborate on why? It seems String + String operations get special treatment from the compiler, does this have anything to do with it?
-
Dan Tao over 13 years@Skurmedal: So, the
+
operator is static, takes two arguments, and returns a new value. You could think of it, really, as a static method. Now, just because a method accepts two arguments and returns a new value does not imply that the type of the arguments is immutable. I couldConcat
twoList<T>
objects together to get a newIEnumerable<T>
without affecting eitherList<T>
; this wouldn't be becauseList<T>
is immutable (it's not). It would just be the wayConcat
works. So even thoughstring
is immutable, it could just as easily not be -- as far as concatenation is concerned. -
Dan Tao over 13 years@Skurmedal: To put it another way: any time I write
x = y + z;
I am assigning a new value to the variablex
. This is unrelated to whetherx
's type is immutable. Immutable type or not, assigning a new value is always going to change what's stored in a variable. Sox = y + z;
is going to change what's atx
, no question. What's really weird to think about is that if the type were mutable, then you could conceivably write the statementx = y + z;
and actually change the value ofy
orz
(or both!) -- if the+
operator for that type were defined to do so. -
Gyle Iverson about 7 yearsThis is the cleanest solution.
-
idbrii almost 5 yearsAnd with format=` "\t{{ {0}, {1} }},\n"`, you get output suitable for copypasting into C#!