最有效的具有格式化功能的 Dictionary.ToString() ?

发布于 2024-09-16 22:37:47 字数 533 浏览 9 评论 0 原文

将字典转换为格式化字符串的最有效方法是什么。

例如:

我的方法:

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 个项目,如果存在另一个类似的“键值对”对象类型,我不会承诺使用它

此外,由于我无论如何都返回字符串,所以会发生什么通用版本是什么样的?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

自此以后,行同陌路 2024-09-23 22:37:47

我刚刚重写了您的版本,使其更加通用并使用 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(); 
}

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(); 
}
神经暖 2024-09-23 22:37:47
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();
}
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();
}
当梦初醒 2024-09-23 22:37:47

此方法的

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}", ", ")

to

a=1, b=2

不要忘记重载:

public static string ToFormattedString<TKey, TValue>(this IDictionary<TKey, TValue> dic)
{
    return dic.ToFormattedString(null, null);
}

您可以使用通用 TKey/TValue 因为任何对象都有 ToString()< /code> 将由 String.Format() 使用。

至于 IDictionaryIEnumerable> 您可以使用任何一个。我更喜欢 IDictionary,因为它具有更多的代码表现力。

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.

萧瑟寒风 2024-09-23 22:37:47

其他答案的略微改进版本,使用扩展方法和默认参数,并将键/值对包装在 {} 中:

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

然后可以直接从字典/枚举调用该方法:

string s = myDict.ItemsToString()

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()
謌踐踏愛綪 2024-09-23 22:37:47

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

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)));
    }
}
情泪▽动烟 2024-09-23 22:37:47

我认为对于只有 10 个字符串,效率几乎不是问题,但也许您不想依赖它只有 10 个。

字符串的串联会在内存中创建一个新的 String 对象,因为 String 对象是不可变的。这也表明其他字符串操作可能会创建新实例,例如替换。通常使用 StringBuilder 可以避免这种情况。

StringBuilder 通过使用它所操作的缓冲区来避免这种情况;当 StringBuilder 的值与另一个 String 连接时,内容将添加到缓冲区的末尾。

不过,也有一些注意事项,请参阅本段

性能考虑

[...]

串联的性能
字符串或的操作
StringBuilder 对象取决于如何
经常会发生内存分配。一个
字符串连接操作始终
分配内存,而a
StringBuilder串联操作
仅在以下情况下分配内存
StringBuilder对象缓冲区太
小以容纳新数据。
因此,String 类是
更适合串联
如果固定数量的 String 则进行操作
对象是串联的。在那
情况下,单独串联
操作甚至可以合并为
编译器的单个操作。一个
StringBuilder 对象更适合
串联操作,如果
任意数量的字符串是
连接;例如,如果一个循环
连接随机数
用户输入的字符串。

因此,像这样的(人为的)情况可能不应该被替换为 StringBuilder:

string addressLine0 = Person.Street.Name +  " " + Person.Street.Number + " Floor " + Person.Street.Floor;

...因为编译器可能能够将其简化为更有效的形式。如果它的效率低到足以在更大的计划中发挥重要作用,也是非常有争议的。

按照 Microsoft 的建议,您可能想改用 StringBuilder (就像其他非常充分的答案所示)。

I think efficiency is hardly a concern with only 10 strings, but maybe you don't want to rely on it only being ten.

Concatenation of Strings creates a new String object in memory, since String objects are immutable. This also suggest other String operations may create new instances, like replace. Usually this is avoided by using StringBuilder.

StringBuilder avoids this by using a buffer which it operates on; when the value of the StringBuilder is concatenated with another String the contents are added to the end of the buffer.

However there are caveats, see this paragraph:

Performance considerations

[...]

The performance of a concatenation
operation for a String or
StringBuilder object depends on how
often a memory allocation occurs. A
String concatenation operation always
allocates memory, whereas a
StringBuilder concatenation operation
only allocates memory if the
StringBuilder object buffer is too
small to accommodate the new data.
Consequently, the String class is
preferable for a concatenation
operation if a fixed number of String
objects are concatenated. In that
case, the individual concatenation
operations might even be combined into
a single operation by the compiler. A
StringBuilder object is preferable for
a concatenation operation if an
arbitrary number of strings are
concatenated; for example, if a loop
concatenates a random number of
strings of user input.

So a (contrived) case like this should probably not be replaced with StringBuilder:

string addressLine0 = Person.Street.Name +  " " + Person.Street.Number + " Floor " + Person.Street.Floor;

...as the compiler might be able to reduce this to a more efficient form. It is also highly debatable if it would inefficient enough to matter in the greater scheme of things.

Following Microsoft's recommendations you probably want to use StringBuilder instead (like the other highly adequate answers show.)

迎风吟唱 2024-09-23 22:37:47

加布,如果你想变得通用,那就通用吧:

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

Gabe, if you are going to be generic, be generic:

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();  
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文