将Dictionary转换为格式化字符串的最有效方法是什么。
e.g:
我的方法:
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;
}
是否有更好/更简洁/更有效的方式?
注意:如果存在另一个类似的“键值对”对象类型,那么词典最多只有10个项目,我不会使用它
另外,既然我无论如何都会返回字符串,那么通用版本会是什么样的呢?
答案 0 :(得分:22)
我刚刚将您的版本改写为更通用,并使用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();
}
答案 1 :(得分:16)
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();
}
答案 2 :(得分:9)
此方法
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)));
}
下一步使用:
dic.ToFormattedString(null, null); // default format and separator
将转换
new Dictionary<string, string>
{
{ "a", "1" },
{ "b", "2" }
};
到
a='1' b='2'
或
dic.ToFormattedString("{0}={1}", ", ")
到
a=1, b=2
不要忘记过载:
public static string ToFormattedString<TKey, TValue>(this IDictionary<TKey, TValue> dic)
{
return dic.ToFormattedString(null, null);
}
您可以使用通用TKey
/ TValue
,因为任何对象都有ToString()
String.Format()
将使用。
至于IDictionary<TKey, TValue>
是IEnumerable<KeyValuePair<TKey, TValue>>
,你可以使用任何。我更喜欢IDictionary以获得更多的代码表达能力。
答案 3 :(得分:3)
使用Linq和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
您可以像这样创建简单的扩展方法:
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)));
}
}
答案 4 :(得分:2)
使用扩展方法和默认参数轻松改进其他答案的版本,并在{}中包装键/值对:
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();
}
然后可以直接从字典/ enumerable中调用该方法:
string s = myDict.ItemsToString()
答案 5 :(得分:1)
我认为只有10个字符串,效率几乎不是问题,但也许你不想仅仅依赖于10个字符串。
字符串的连接在内存中创建一个新的String对象,因为String对象是不可变的。这也表明其他String操作可能会创建新实例,例如replace。通常使用StringBuilder可以避免这种情况。
StringBuilder通过使用它运行的缓冲区来避免这种情况;当StringBuilder的值与另一个String连接时,内容将被添加到缓冲区的末尾。
但有一些警告,请参阅this paragraph:
效果考虑因素
[...]
串联的表现 String或的操作 StringBuilder对象取决于方式 通常会发生内存分配。一个 字符串连接操作始终 分配内存,而a StringBuilder连接操作 只有分配内存 StringBuilder对象缓冲区也是如此 小到容纳新数据。 因此,String类是 最好是串联 操作如果是固定数量的String 对象是连接的。在那里面 个案,个别串联 甚至可以将操作合并到一起 编译器的单个操作。一个 StringBuilder对象更适合 一个连接操作,如果一个 任意数量的字符串 级联;例如,如果一个循环 连接随机数 用户输入字符串。
因此,像这样的(人为的)案例可能不应该被StringBuilder取代:
string addressLine0 = Person.Street.Name + " " + Person.Street.Number + " Floor " + Person.Street.Floor;
...因为编译器可能能够将其减少到更有效的形式。如果在更大的方案中它足够低效,那么它也是值得商榷的。
根据Microsoft的建议,您可能希望使用StringBuilder(就像其他非常适当的答案所示。)
答案 6 :(得分:0)
Gabe,如果你是通用的,那就是通用的:
public string DictToString<T>(IDictionary<string, T> 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();
}