Самый эффективный словарь.ToString () с форматированием? - PullRequest
10 голосов
/ 03 сентября 2010

Какой самый эффективный способ преобразовать словарь в форматированную строку.

Например:

Мой метод:

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 элементов, и я не намерен использовать его, если существует другой аналогичный тип объекта "пара ключ-значение"

Кроме того, поскольку я все равно возвращаю строки, как будет выглядеть универсальная версия?

Ответы [ 7 ]

22 голосов
/ 03 сентября 2010

Я просто переписал вашу версию, чтобы она была немного более обобщенной и использовал 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(); 
}
16 голосов
/ 03 сентября 2010
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();
}
9 голосов
/ 04 сентября 2010

Этот метод

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 голосов
/ 02 марта 2017

Форматировать словарь в одну строку с помощью 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)));
    }
}
2 голосов
/ 19 октября 2016

Немного улучшенная версия других ответов, с использованием методов расширения и параметров по умолчанию, а также упаковка пар ключ / значение в {}:

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()
1 голос
/ 04 сентября 2010

Я думаю, что эффективность - это не проблема только с 10 строками, но, может быть, вы не хотите полагаться на то, что только десять.

Конкатенация строк создает новый объект String в памяти, поскольку объекты String являются неизменяемыми. Это также предполагает, что другие операции String могут создавать новые экземпляры, такие как replace. Обычно этого можно избежать с помощью StringBuilder.

StringBuilder избегает этого, используя буфер, с которым он работает; когда значение StringBuilder объединяется с другой строкой, содержимое добавляется в конец буфера.

Однако есть предостережения, см. этот абзац :

Особенности производительности

[...]

Производительность конкатенации операция для строки или Объект StringBuilder зависит от того, как часто происходит выделение памяти. Операция конкатенации строк всегда выделяет память, тогда как Операция конкатенации StringBuilder только выделяет память, если Буфер объекта StringBuilder слишком маленький для размещения новых данных. Следовательно, класс String предпочтительнее для объединения операция, если фиксированное число строк объекты объединены. В этом случай, индивидуальная конкатенация операции могут быть даже объединены в одна операция компилятора. Объект StringBuilder предпочтительнее для операция конкатенации, если произвольное количество строк сцеплены; например, если цикл объединяет случайное число строки пользовательского ввода.

Так что (надуманный) случай, подобный этому, вероятно, не следует заменять на StringBuilder:

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

... так как компилятор может уменьшить это до более эффективной формы. Кроме того, весьма спорно, если бы достаточно неэффективные материй в большей схеме вещей.

Следуя рекомендациям Microsoft, вы, вероятно, хотите вместо этого использовать StringBuilder (как показывают другие весьма адекватные ответы).

0 голосов
/ 04 сентября 2010

Гейб, если ты собираешься быть родовым, будь родовым:

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