2010-01-06 2 views
10

строку для создания с помощью KeyValuePair, как это: "name1 = v1 & name2 = v2 & name3 = v3"элегантный способ построить строку в C#

, что я делаю:

var sb = new StringBuilder(); 

foreach (var name in nameValues) 
{ 
      sb.AppendFormat("{0}={1}&", name.Key, name.Value); 
} 

//remove last '&' sign, this is what i think is ugly 
sb.ToString().Remove(lastIndex); 

любой элегантный способ избежать последней инструкции по удалению '&' знак?

+0

Я думаю, что это лучший способ вы делаете это, избегайте дополнительных проверок для каждой итерации, показанной ниже. – Ravia

ответ

18
var joined = 
    String.Join("&", nameValues.Select(n => n.Key + "=" + n.Value).ToArray()); 

Учитывая, что мы не конкатенации на одну большую строку (мы производим много маленьких струн), конкатенация не несет никаких штрафных санкций в этом случае. И в .NET строки имеют префикс длины, так что вся проблема производительности конкатенации менее актуальна, чем в C. String.Join() также очень быстро, быстрее, чем StringBuilder.

TLDR: Использование String.Join()

+0

Вы забыли «n =>» в Выбрать. var join = String.Join ("&", nameValues.Select (n => String.Concat (n.Key, "=", n.Value)). ToArray()); – helium

+0

helium: Да, я знаю, что исправил это. Я еще не проснулся на 100%. –

+1

прохладный. присоединиться удивительно – Benny

1

Ну по крайней мере, вы можете удалить & знак перед ToString() вызова, делая --sb.Length;

4
foreach (var name in nameValues) 
    { 
     if (sb.Length > 0) sb.Append("&"); 
       sb.AppendFormat("{0}={1}", name.Key, name.Value); 
    } 

Просто добавьте «&», когда это необходимо, не снимайте его с конца.

+3

И если скорость вызывает беспокойство, используйте sb.Append (name.Key) .Append ("="). Append (name.Value); – Will

5

Посмотрите здесь: How to build a query string for a URL in C#?; Цитирование:

private string ToQueryString(NameValueCollection nvc) 
{ 
    return "?" + 
     string.Join("&", 
      Array.ConvertAll(
       nvc.AllKeys, 
       key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), 
       HttpUtility.UrlEncode(nvc[key])))); 
} 
+0

cuil! это будет выглядеть более круто, если его можно использовать как метод расширения. –

+0

Есть ли имяValueCollection, которое может содержать строку, пару объектов? – Benny

+0

Не можете ли вы использовать словарь '? –

0
var sb = new StringBuilder(); 

sb.AppendFormat("{0}={1}", nameValues[0].Key, nameValues[0].Value); 

for (int i = 1; i < nameValues.Count; i++) 
{ 
     sb.AppendFormat("&{0}={1}", nameValues[i].Key, nameValues[i].Value); 
} 
+0

Маленькая опечатка на первом AppendFormat - ей не нужно «&». Этот метод отлично работает, если гарантируется хотя бы одна запись. – Will

3

Вот еще один подход, который я иногда использовал:

var sb = new StringBuilder(); 
string prefix = ""; 
foreach (var name in nameValues) 
{ 
    sb.Append(prefix); 
    prefix = "&"; 
    sb.AppendFormat("{0}={1}", name.Key, name.Value); 
} 

Это просто способ предваряя & перед каждой парой, кроме первого, не используя условный тест.

Если вы хотите использовать свою оригинальную идею обрезки StringBuilder, кстати, я хотел бы предложить следующий код вместо:

sb.Length--; // Remove the last character 
return sb.ToString(); 
+1

cool, sb.Length-- эффективнее. – Benny

+2

Вы также можете пойти с символом '' & {0} = {1} "' и нарисовать символ _first_ с помощью 'sb.ToString (1, sb.Length - 1)' –

3

Я предпочитаю использовать это, используя тот факт, вы можете обрезать строку строитель с декремента на свойстве длина:

var sb = new StringBuilder(); 

foreach (var name in nameValues) 
{ 
    sb.AppendFormat("{0}={1}&", name.Key, name.Value); 
} 

if (sb.Length > 0) sb.Length--; 
Смежные вопросы